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; 77 RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {} 78 79 /// It might return null. 80 const MemRegion *getRegion() const { return R; } 81 82 bool hasSymbolicOffset() const { return Offset == Symbolic; } 83 84 int64_t getOffset() const { 85 assert(!hasSymbolicOffset()); 86 return Offset; 87 } 88 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: 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 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 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 212 MemSpaceRegion(MemRegionManager &mgr, Kind k) : MemRegion(k), Mgr(mgr) { 213 assert(classof(this)); 214 } 215 216 MemRegionManager &getMemRegionManager() const override { return Mgr; } 217 218 public: 219 bool isBoundable() const override { return false; } 220 221 void Profile(llvm::FoldingSetNodeID &ID) const override; 222 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 234 CodeSpaceRegion(MemRegionManager &mgr) 235 : MemSpaceRegion(mgr, CodeSpaceRegionKind) {} 236 237 public: 238 void dumpToStream(raw_ostream &os) const override; 239 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: 249 GlobalsSpaceRegion(MemRegionManager &mgr, Kind k) : MemSpaceRegion(mgr, k) { 250 assert(classof(this)); 251 } 252 253 public: 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 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 281 const CodeTextRegion *getCodeRegion() const { return CR; } 282 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: 298 NonStaticGlobalSpaceRegion(MemRegionManager &mgr, Kind k) 299 : GlobalsSpaceRegion(mgr, k) { 300 assert(classof(this)); 301 } 302 303 public: 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 316 GlobalSystemSpaceRegion(MemRegionManager &mgr) 317 : NonStaticGlobalSpaceRegion(mgr, GlobalSystemSpaceRegionKind) {} 318 319 public: 320 void dumpToStream(raw_ostream &os) const override; 321 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 335 GlobalImmutableSpaceRegion(MemRegionManager &mgr) 336 : NonStaticGlobalSpaceRegion(mgr, GlobalImmutableSpaceRegionKind) {} 337 338 public: 339 void dumpToStream(raw_ostream &os) const override; 340 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 352 GlobalInternalSpaceRegion(MemRegionManager &mgr) 353 : NonStaticGlobalSpaceRegion(mgr, GlobalInternalSpaceRegionKind) {} 354 355 public: 356 void dumpToStream(raw_ostream &os) const override; 357 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 366 HeapSpaceRegion(MemRegionManager &mgr) 367 : MemSpaceRegion(mgr, HeapSpaceRegionKind) {} 368 369 public: 370 void dumpToStream(raw_ostream &os) const override; 371 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 380 UnknownSpaceRegion(MemRegionManager &mgr) 381 : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {} 382 383 public: 384 void dumpToStream(raw_ostream &os) const override; 385 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: 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 405 const StackFrameContext *getStackFrame() const { return SFC; } 406 407 void Profile(llvm::FoldingSetNodeID &ID) const override; 408 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 418 StackLocalsSpaceRegion(MemRegionManager &mgr, const StackFrameContext *sfc) 419 : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {} 420 421 public: 422 void dumpToStream(raw_ostream &os) const override; 423 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 433 StackArgumentsSpaceRegion(MemRegionManager &mgr, const StackFrameContext *sfc) 434 : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {} 435 436 public: 437 void dumpToStream(raw_ostream &os) const override; 438 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 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 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 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 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 497 const Expr *getExpr() const { return Ex; } 498 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 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: 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 522 QualType getDesugaredLocationType(ASTContext &Context) const { 523 return getLocationType().getDesugaredType(Context); 524 } 525 526 bool isBoundable() const override { return true; } 527 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: 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 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 555 QualType getDesugaredValueType(ASTContext &Context) const { 556 QualType T = getValueType(); 557 return T.getTypePtrOrNull() ? T.getDesugaredType(Context) : T; 558 } 559 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: 570 CodeTextRegion(const MemSpaceRegion *sreg, Kind k) : TypedRegion(sreg, k) { 571 assert(classof(this)); 572 } 573 574 public: 575 bool isBoundable() const override { return false; } 576 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 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: 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 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 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 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: 651 QualType getLocationType() const override { 652 return locTy; 653 } 654 655 LLVM_ATTRIBUTE_RETURNS_NONNULL 656 const BlockDecl *getDecl() const { 657 return BD; 658 } 659 660 LLVM_ATTRIBUTE_RETURNS_NONNULL 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 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 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 705 const BlockCodeRegion *getCodeRegion() const { return BC; } 706 707 LLVM_ATTRIBUTE_RETURNS_NONNULL 708 const BlockDecl *getDecl() const { return BC->getDecl(); } 709 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: 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 722 const VarRegion *getCapturedRegion() const { 723 return cast<VarRegion>(*R); 724 } 725 726 LLVM_ATTRIBUTE_RETURNS_NONNULL 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 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 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. 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. 809 QualType getPointeeStaticType() const { 810 return sym->getType()->getPointeeType(); 811 } 812 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 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 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 845 const StringLiteral *getStringLiteral() const { return Str; } 846 847 QualType getValueType() const override { return Str->getType(); } 848 849 bool isBoundable() const override { return false; } 850 851 void Profile(llvm::FoldingSetNodeID& ID) const override { 852 ProfileRegion(ID, Str, superRegion); 853 } 854 855 void dumpToStream(raw_ostream &os) const override; 856 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 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 880 const ObjCStringLiteral *getObjCStringLiteral() const { return Str; } 881 882 QualType getValueType() const override { return Str->getType(); } 883 884 bool isBoundable() const override { return false; } 885 886 void Profile(llvm::FoldingSetNodeID& ID) const override { 887 ProfileRegion(ID, Str, superRegion); 888 } 889 890 void dumpToStream(raw_ostream &os) const override; 891 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 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: 918 QualType getValueType() const override { return CL->getType(); } 919 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 927 const CompoundLiteralExpr *getLiteralExpr() const { return CL; } 928 929 static bool classof(const MemRegion* R) { 930 return R->getKind() == CompoundLiteralRegionKind; 931 } 932 }; 933 934 class DeclRegion : public TypedValueRegion { 935 protected: 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 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. 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 971 QualType getValueType() const override { 972 // FIXME: We can cache this if needed. 973 return getDecl()->getType(); 974 } 975 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. 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 1006 const VarDecl *getDecl() const override { return VD; } 1007 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 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 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 1051 const Expr *getOriginExpr() const { return OriginExpr; } 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 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 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 1092 QualType getValueType() const override { 1093 return QualType(ThisPointerTy, 0); 1094 } 1095 1096 void dumpToStream(raw_ostream &os) const override; 1097 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 1111 FieldRegion(const FieldDecl *fd, const SubRegion *sReg) 1112 : DeclRegion(sReg, FieldRegionKind), FD(fd) { 1113 assert(FD); 1114 } 1115 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 1125 const FieldDecl *getDecl() const override { return FD; } 1126 1127 void Profile(llvm::FoldingSetNodeID &ID) const override; 1128 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 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 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()) 1185 : Region(reg), Offset(offset) {} 1186 1187 public: 1188 // FIXME: Eventually support symbolic offsets. 1189 CharUnits getOffset() const { return Offset; } 1190 1191 // It might return null. 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 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: 1219 NonLoc getIndex() const { return Index; } 1220 1221 QualType getValueType() const override { return ElementType; } 1222 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 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 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 1254 const Expr *getExpr() const { return Ex; } 1255 1256 LLVM_ATTRIBUTE_RETURNS_NONNULL 1257 const StackFrameContext *getStackFrame() const; 1258 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 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 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 1292 const Expr *getExpr() const { return Ex; } 1293 LLVM_ATTRIBUTE_RETURNS_NONNULL 1294 const ValueDecl *getExtendingDecl() const { return ExD; } 1295 /// It might return null. 1296 const StackFrameContext *getStackFrame() const; 1297 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 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 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 1327 const CXXRecordDecl *getDecl() const { return Data.getPointer(); } 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 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 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 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 1382 static bool classof(const MemRegion *region) { 1383 return region->getKind() == CXXDerivedObjectRegionKind; 1384 } 1385 }; 1386 1387 template<typename RegionTy> 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> 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: 1426 MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a) : Ctx(c), A(a) {} 1427 ~MemRegionManager(); 1428 1429 ASTContext &getContext() { return Ctx; } 1430 const ASTContext &getContext() const { return Ctx; } 1431 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 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 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 * 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 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