1 //== MemRegion.cpp - Abstract memory regions for static analysis --*- C++ -*--// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines MemRegion and its subclasses. MemRegion defines a 11 // partially-typed abstraction of memory useful for path-sensitive dataflow 12 // analyses. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" 17 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" 18 #include "clang/Analysis/AnalysisContext.h" 19 #include "clang/Analysis/Support/BumpVector.h" 20 #include "clang/AST/CharUnits.h" 21 #include "clang/AST/RecordLayout.h" 22 #include "clang/Basic/SourceManager.h" 23 #include "llvm/Support/raw_ostream.h" 24 25 using namespace clang; 26 using namespace ento; 27 28 //===----------------------------------------------------------------------===// 29 // MemRegion Construction. 30 //===----------------------------------------------------------------------===// 31 32 template<typename RegionTy> struct MemRegionManagerTrait; 33 34 template <typename RegionTy, typename A1> 35 RegionTy* MemRegionManager::getRegion(const A1 a1) { 36 37 const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion = 38 MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1); 39 40 llvm::FoldingSetNodeID ID; 41 RegionTy::ProfileRegion(ID, a1, superRegion); 42 void *InsertPos; 43 RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, 44 InsertPos)); 45 46 if (!R) { 47 R = (RegionTy*) A.Allocate<RegionTy>(); 48 new (R) RegionTy(a1, superRegion); 49 Regions.InsertNode(R, InsertPos); 50 } 51 52 return R; 53 } 54 55 template <typename RegionTy, typename A1> 56 RegionTy* MemRegionManager::getSubRegion(const A1 a1, 57 const MemRegion *superRegion) { 58 llvm::FoldingSetNodeID ID; 59 RegionTy::ProfileRegion(ID, a1, superRegion); 60 void *InsertPos; 61 RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, 62 InsertPos)); 63 64 if (!R) { 65 R = (RegionTy*) A.Allocate<RegionTy>(); 66 new (R) RegionTy(a1, superRegion); 67 Regions.InsertNode(R, InsertPos); 68 } 69 70 return R; 71 } 72 73 template <typename RegionTy, typename A1, typename A2> 74 RegionTy* MemRegionManager::getRegion(const A1 a1, const A2 a2) { 75 76 const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion = 77 MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1, a2); 78 79 llvm::FoldingSetNodeID ID; 80 RegionTy::ProfileRegion(ID, a1, a2, superRegion); 81 void *InsertPos; 82 RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, 83 InsertPos)); 84 85 if (!R) { 86 R = (RegionTy*) A.Allocate<RegionTy>(); 87 new (R) RegionTy(a1, a2, superRegion); 88 Regions.InsertNode(R, InsertPos); 89 } 90 91 return R; 92 } 93 94 template <typename RegionTy, typename A1, typename A2> 95 RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2, 96 const MemRegion *superRegion) { 97 98 llvm::FoldingSetNodeID ID; 99 RegionTy::ProfileRegion(ID, a1, a2, superRegion); 100 void *InsertPos; 101 RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, 102 InsertPos)); 103 104 if (!R) { 105 R = (RegionTy*) A.Allocate<RegionTy>(); 106 new (R) RegionTy(a1, a2, superRegion); 107 Regions.InsertNode(R, InsertPos); 108 } 109 110 return R; 111 } 112 113 template <typename RegionTy, typename A1, typename A2, typename A3> 114 RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2, const A3 a3, 115 const MemRegion *superRegion) { 116 117 llvm::FoldingSetNodeID ID; 118 RegionTy::ProfileRegion(ID, a1, a2, a3, superRegion); 119 void *InsertPos; 120 RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, 121 InsertPos)); 122 123 if (!R) { 124 R = (RegionTy*) A.Allocate<RegionTy>(); 125 new (R) RegionTy(a1, a2, a3, superRegion); 126 Regions.InsertNode(R, InsertPos); 127 } 128 129 return R; 130 } 131 132 //===----------------------------------------------------------------------===// 133 // Object destruction. 134 //===----------------------------------------------------------------------===// 135 136 MemRegion::~MemRegion() {} 137 138 MemRegionManager::~MemRegionManager() { 139 // All regions and their data are BumpPtrAllocated. No need to call 140 // their destructors. 141 } 142 143 //===----------------------------------------------------------------------===// 144 // Basic methods. 145 //===----------------------------------------------------------------------===// 146 147 bool SubRegion::isSubRegionOf(const MemRegion* R) const { 148 const MemRegion* r = getSuperRegion(); 149 while (r != 0) { 150 if (r == R) 151 return true; 152 if (const SubRegion* sr = dyn_cast<SubRegion>(r)) 153 r = sr->getSuperRegion(); 154 else 155 break; 156 } 157 return false; 158 } 159 160 MemRegionManager* SubRegion::getMemRegionManager() const { 161 const SubRegion* r = this; 162 do { 163 const MemRegion *superRegion = r->getSuperRegion(); 164 if (const SubRegion *sr = dyn_cast<SubRegion>(superRegion)) { 165 r = sr; 166 continue; 167 } 168 return superRegion->getMemRegionManager(); 169 } while (1); 170 } 171 172 const StackFrameContext *VarRegion::getStackFrame() const { 173 const StackSpaceRegion *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace()); 174 return SSR ? SSR->getStackFrame() : NULL; 175 } 176 177 //===----------------------------------------------------------------------===// 178 // Region extents. 179 //===----------------------------------------------------------------------===// 180 181 DefinedOrUnknownSVal DeclRegion::getExtent(SValBuilder &svalBuilder) const { 182 ASTContext &Ctx = svalBuilder.getContext(); 183 QualType T = getDesugaredValueType(Ctx); 184 185 if (isa<VariableArrayType>(T)) 186 return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this)); 187 if (isa<IncompleteArrayType>(T)) 188 return UnknownVal(); 189 190 CharUnits size = Ctx.getTypeSizeInChars(T); 191 QualType sizeTy = svalBuilder.getArrayIndexType(); 192 return svalBuilder.makeIntVal(size.getQuantity(), sizeTy); 193 } 194 195 DefinedOrUnknownSVal FieldRegion::getExtent(SValBuilder &svalBuilder) const { 196 DefinedOrUnknownSVal Extent = DeclRegion::getExtent(svalBuilder); 197 198 // A zero-length array at the end of a struct often stands for dynamically- 199 // allocated extra memory. 200 if (Extent.isZeroConstant()) { 201 QualType T = getDesugaredValueType(svalBuilder.getContext()); 202 203 if (isa<ConstantArrayType>(T)) 204 return UnknownVal(); 205 } 206 207 return Extent; 208 } 209 210 DefinedOrUnknownSVal AllocaRegion::getExtent(SValBuilder &svalBuilder) const { 211 return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this)); 212 } 213 214 DefinedOrUnknownSVal SymbolicRegion::getExtent(SValBuilder &svalBuilder) const { 215 return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this)); 216 } 217 218 DefinedOrUnknownSVal StringRegion::getExtent(SValBuilder &svalBuilder) const { 219 return svalBuilder.makeIntVal(getStringLiteral()->getByteLength()+1, 220 svalBuilder.getArrayIndexType()); 221 } 222 223 QualType CXXBaseObjectRegion::getValueType() const { 224 return QualType(decl->getTypeForDecl(), 0); 225 } 226 227 //===----------------------------------------------------------------------===// 228 // FoldingSet profiling. 229 //===----------------------------------------------------------------------===// 230 231 void MemSpaceRegion::Profile(llvm::FoldingSetNodeID& ID) const { 232 ID.AddInteger((unsigned)getKind()); 233 } 234 235 void StackSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const { 236 ID.AddInteger((unsigned)getKind()); 237 ID.AddPointer(getStackFrame()); 238 } 239 240 void StaticGlobalSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const { 241 ID.AddInteger((unsigned)getKind()); 242 ID.AddPointer(getCodeRegion()); 243 } 244 245 void StringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 246 const StringLiteral* Str, 247 const MemRegion* superRegion) { 248 ID.AddInteger((unsigned) StringRegionKind); 249 ID.AddPointer(Str); 250 ID.AddPointer(superRegion); 251 } 252 253 void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 254 const Expr *Ex, unsigned cnt, 255 const MemRegion *) { 256 ID.AddInteger((unsigned) AllocaRegionKind); 257 ID.AddPointer(Ex); 258 ID.AddInteger(cnt); 259 } 260 261 void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const { 262 ProfileRegion(ID, Ex, Cnt, superRegion); 263 } 264 265 void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const { 266 CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion); 267 } 268 269 void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 270 const CompoundLiteralExpr *CL, 271 const MemRegion* superRegion) { 272 ID.AddInteger((unsigned) CompoundLiteralRegionKind); 273 ID.AddPointer(CL); 274 ID.AddPointer(superRegion); 275 } 276 277 void CXXThisRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, 278 const PointerType *PT, 279 const MemRegion *sRegion) { 280 ID.AddInteger((unsigned) CXXThisRegionKind); 281 ID.AddPointer(PT); 282 ID.AddPointer(sRegion); 283 } 284 285 void CXXThisRegion::Profile(llvm::FoldingSetNodeID &ID) const { 286 CXXThisRegion::ProfileRegion(ID, ThisPointerTy, superRegion); 287 } 288 289 void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D, 290 const MemRegion* superRegion, Kind k) { 291 ID.AddInteger((unsigned) k); 292 ID.AddPointer(D); 293 ID.AddPointer(superRegion); 294 } 295 296 void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const { 297 DeclRegion::ProfileRegion(ID, D, superRegion, getKind()); 298 } 299 300 void VarRegion::Profile(llvm::FoldingSetNodeID &ID) const { 301 VarRegion::ProfileRegion(ID, getDecl(), superRegion); 302 } 303 304 void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym, 305 const MemRegion *sreg) { 306 ID.AddInteger((unsigned) MemRegion::SymbolicRegionKind); 307 ID.Add(sym); 308 ID.AddPointer(sreg); 309 } 310 311 void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const { 312 SymbolicRegion::ProfileRegion(ID, sym, getSuperRegion()); 313 } 314 315 void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 316 QualType ElementType, SVal Idx, 317 const MemRegion* superRegion) { 318 ID.AddInteger(MemRegion::ElementRegionKind); 319 ID.Add(ElementType); 320 ID.AddPointer(superRegion); 321 Idx.Profile(ID); 322 } 323 324 void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const { 325 ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion); 326 } 327 328 void FunctionTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 329 const FunctionDecl *FD, 330 const MemRegion*) { 331 ID.AddInteger(MemRegion::FunctionTextRegionKind); 332 ID.AddPointer(FD); 333 } 334 335 void FunctionTextRegion::Profile(llvm::FoldingSetNodeID& ID) const { 336 FunctionTextRegion::ProfileRegion(ID, FD, superRegion); 337 } 338 339 void BlockTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 340 const BlockDecl *BD, CanQualType, 341 const AnalysisDeclContext *AC, 342 const MemRegion*) { 343 ID.AddInteger(MemRegion::BlockTextRegionKind); 344 ID.AddPointer(BD); 345 } 346 347 void BlockTextRegion::Profile(llvm::FoldingSetNodeID& ID) const { 348 BlockTextRegion::ProfileRegion(ID, BD, locTy, AC, superRegion); 349 } 350 351 void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 352 const BlockTextRegion *BC, 353 const LocationContext *LC, 354 const MemRegion *sReg) { 355 ID.AddInteger(MemRegion::BlockDataRegionKind); 356 ID.AddPointer(BC); 357 ID.AddPointer(LC); 358 ID.AddPointer(sReg); 359 } 360 361 void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const { 362 BlockDataRegion::ProfileRegion(ID, BC, LC, getSuperRegion()); 363 } 364 365 void CXXTempObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, 366 Expr const *Ex, 367 const MemRegion *sReg) { 368 ID.AddPointer(Ex); 369 ID.AddPointer(sReg); 370 } 371 372 void CXXTempObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { 373 ProfileRegion(ID, Ex, getSuperRegion()); 374 } 375 376 void CXXBaseObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, 377 const CXXRecordDecl *decl, 378 const MemRegion *sReg) { 379 ID.AddPointer(decl); 380 ID.AddPointer(sReg); 381 } 382 383 void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { 384 ProfileRegion(ID, decl, superRegion); 385 } 386 387 //===----------------------------------------------------------------------===// 388 // Region anchors. 389 //===----------------------------------------------------------------------===// 390 391 void GlobalsSpaceRegion::anchor() { } 392 void HeapSpaceRegion::anchor() { } 393 void UnknownSpaceRegion::anchor() { } 394 void StackLocalsSpaceRegion::anchor() { } 395 void StackArgumentsSpaceRegion::anchor() { } 396 void TypedRegion::anchor() { } 397 void TypedValueRegion::anchor() { } 398 void CodeTextRegion::anchor() { } 399 void SubRegion::anchor() { } 400 401 //===----------------------------------------------------------------------===// 402 // Region pretty-printing. 403 //===----------------------------------------------------------------------===// 404 405 void MemRegion::dump() const { 406 dumpToStream(llvm::errs()); 407 } 408 409 std::string MemRegion::getString() const { 410 std::string s; 411 llvm::raw_string_ostream os(s); 412 dumpToStream(os); 413 return os.str(); 414 } 415 416 void MemRegion::dumpToStream(raw_ostream &os) const { 417 os << "<Unknown Region>"; 418 } 419 420 void AllocaRegion::dumpToStream(raw_ostream &os) const { 421 os << "alloca{" << (void*) Ex << ',' << Cnt << '}'; 422 } 423 424 void FunctionTextRegion::dumpToStream(raw_ostream &os) const { 425 os << "code{" << getDecl()->getDeclName().getAsString() << '}'; 426 } 427 428 void BlockTextRegion::dumpToStream(raw_ostream &os) const { 429 os << "block_code{" << (void*) this << '}'; 430 } 431 432 void BlockDataRegion::dumpToStream(raw_ostream &os) const { 433 os << "block_data{" << BC << '}'; 434 } 435 436 void CompoundLiteralRegion::dumpToStream(raw_ostream &os) const { 437 // FIXME: More elaborate pretty-printing. 438 os << "{ " << (void*) CL << " }"; 439 } 440 441 void CXXTempObjectRegion::dumpToStream(raw_ostream &os) const { 442 os << "temp_object{" << getValueType().getAsString() << ',' 443 << (void*) Ex << '}'; 444 } 445 446 void CXXBaseObjectRegion::dumpToStream(raw_ostream &os) const { 447 os << "base " << decl->getName(); 448 } 449 450 void CXXThisRegion::dumpToStream(raw_ostream &os) const { 451 os << "this"; 452 } 453 454 void ElementRegion::dumpToStream(raw_ostream &os) const { 455 os << "element{" << superRegion << ',' 456 << Index << ',' << getElementType().getAsString() << '}'; 457 } 458 459 void FieldRegion::dumpToStream(raw_ostream &os) const { 460 os << superRegion << "->" << *getDecl(); 461 } 462 463 void ObjCIvarRegion::dumpToStream(raw_ostream &os) const { 464 os << "ivar{" << superRegion << ',' << *getDecl() << '}'; 465 } 466 467 void StringRegion::dumpToStream(raw_ostream &os) const { 468 Str->printPretty(os, 0, PrintingPolicy(getContext().getLangOptions())); 469 } 470 471 void SymbolicRegion::dumpToStream(raw_ostream &os) const { 472 os << "SymRegion{" << sym << '}'; 473 } 474 475 void VarRegion::dumpToStream(raw_ostream &os) const { 476 os << *cast<VarDecl>(D); 477 } 478 479 void RegionRawOffset::dump() const { 480 dumpToStream(llvm::errs()); 481 } 482 483 void RegionRawOffset::dumpToStream(raw_ostream &os) const { 484 os << "raw_offset{" << getRegion() << ',' << getOffset().getQuantity() << '}'; 485 } 486 487 void StaticGlobalSpaceRegion::dumpToStream(raw_ostream &os) const { 488 os << "StaticGlobalsMemSpace{" << CR << '}'; 489 } 490 491 void NonStaticGlobalSpaceRegion::dumpToStream(raw_ostream &os) const { 492 os << "NonStaticGlobalSpaceRegion"; 493 } 494 495 void GlobalInternalSpaceRegion::dumpToStream(raw_ostream &os) const { 496 os << "GlobalInternalSpaceRegion"; 497 } 498 499 void GlobalSystemSpaceRegion::dumpToStream(raw_ostream &os) const { 500 os << "GlobalSystemSpaceRegion"; 501 } 502 503 void GlobalImmutableSpaceRegion::dumpToStream(raw_ostream &os) const { 504 os << "GlobalImmutableSpaceRegion"; 505 } 506 507 //===----------------------------------------------------------------------===// 508 // MemRegionManager methods. 509 //===----------------------------------------------------------------------===// 510 511 template <typename REG> 512 const REG *MemRegionManager::LazyAllocate(REG*& region) { 513 if (!region) { 514 region = (REG*) A.Allocate<REG>(); 515 new (region) REG(this); 516 } 517 518 return region; 519 } 520 521 template <typename REG, typename ARG> 522 const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) { 523 if (!region) { 524 region = (REG*) A.Allocate<REG>(); 525 new (region) REG(this, a); 526 } 527 528 return region; 529 } 530 531 const StackLocalsSpaceRegion* 532 MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) { 533 assert(STC); 534 StackLocalsSpaceRegion *&R = StackLocalsSpaceRegions[STC]; 535 536 if (R) 537 return R; 538 539 R = A.Allocate<StackLocalsSpaceRegion>(); 540 new (R) StackLocalsSpaceRegion(this, STC); 541 return R; 542 } 543 544 const StackArgumentsSpaceRegion * 545 MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) { 546 assert(STC); 547 StackArgumentsSpaceRegion *&R = StackArgumentsSpaceRegions[STC]; 548 549 if (R) 550 return R; 551 552 R = A.Allocate<StackArgumentsSpaceRegion>(); 553 new (R) StackArgumentsSpaceRegion(this, STC); 554 return R; 555 } 556 557 const GlobalsSpaceRegion 558 *MemRegionManager::getGlobalsRegion(MemRegion::Kind K, 559 const CodeTextRegion *CR) { 560 if (!CR) { 561 if (K == MemRegion::GlobalSystemSpaceRegionKind) 562 return LazyAllocate(SystemGlobals); 563 if (K == MemRegion::GlobalImmutableSpaceRegionKind) 564 return LazyAllocate(ImmutableGlobals); 565 assert(K == MemRegion::GlobalInternalSpaceRegionKind); 566 return LazyAllocate(InternalGlobals); 567 } 568 569 assert(K == MemRegion::StaticGlobalSpaceRegionKind); 570 StaticGlobalSpaceRegion *&R = StaticsGlobalSpaceRegions[CR]; 571 if (R) 572 return R; 573 574 R = A.Allocate<StaticGlobalSpaceRegion>(); 575 new (R) StaticGlobalSpaceRegion(this, CR); 576 return R; 577 } 578 579 const HeapSpaceRegion *MemRegionManager::getHeapRegion() { 580 return LazyAllocate(heap); 581 } 582 583 const MemSpaceRegion *MemRegionManager::getUnknownRegion() { 584 return LazyAllocate(unknown); 585 } 586 587 const MemSpaceRegion *MemRegionManager::getCodeRegion() { 588 return LazyAllocate(code); 589 } 590 591 //===----------------------------------------------------------------------===// 592 // Constructing regions. 593 //===----------------------------------------------------------------------===// 594 const StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str){ 595 return getSubRegion<StringRegion>(Str, getGlobalsRegion()); 596 } 597 598 const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D, 599 const LocationContext *LC) { 600 const MemRegion *sReg = 0; 601 602 if (D->hasGlobalStorage() && !D->isStaticLocal()) { 603 604 // First handle the globals defined in system headers. 605 if (C.getSourceManager().isInSystemHeader(D->getLocation())) { 606 // Whitelist the system globals which often DO GET modified, assume the 607 // rest are immutable. 608 if (D->getName().find("errno") != StringRef::npos) 609 sReg = getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind); 610 else 611 sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); 612 613 // Treat other globals as GlobalInternal unless they are constants. 614 } else { 615 QualType GQT = D->getType(); 616 const Type *GT = GQT.getTypePtrOrNull(); 617 // TODO: We could walk the complex types here and see if everything is 618 // constified. 619 if (GT && GQT.isConstQualified() && GT->isArithmeticType()) 620 sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); 621 else 622 sReg = getGlobalsRegion(); 623 } 624 625 // Finally handle static locals. 626 } else { 627 // FIXME: Once we implement scope handling, we will need to properly lookup 628 // 'D' to the proper LocationContext. 629 const DeclContext *DC = D->getDeclContext(); 630 const StackFrameContext *STC = LC->getStackFrameForDeclContext(DC); 631 632 if (!STC) 633 sReg = getUnknownRegion(); 634 else { 635 if (D->hasLocalStorage()) { 636 sReg = isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) 637 ? static_cast<const MemRegion*>(getStackArgumentsRegion(STC)) 638 : static_cast<const MemRegion*>(getStackLocalsRegion(STC)); 639 } 640 else { 641 assert(D->isStaticLocal()); 642 const Decl *D = STC->getDecl(); 643 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 644 sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, 645 getFunctionTextRegion(FD)); 646 else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { 647 const BlockTextRegion *BTR = 648 getBlockTextRegion(BD, 649 C.getCanonicalType(BD->getSignatureAsWritten()->getType()), 650 STC->getAnalysisDeclContext()); 651 sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, 652 BTR); 653 } 654 else { 655 // FIXME: For ObjC-methods, we need a new CodeTextRegion. For now 656 // just use the main global memspace. 657 sReg = getGlobalsRegion(); 658 } 659 } 660 } 661 } 662 663 return getSubRegion<VarRegion>(D, sReg); 664 } 665 666 const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D, 667 const MemRegion *superR) { 668 return getSubRegion<VarRegion>(D, superR); 669 } 670 671 const BlockDataRegion * 672 MemRegionManager::getBlockDataRegion(const BlockTextRegion *BC, 673 const LocationContext *LC) { 674 const MemRegion *sReg = 0; 675 676 if (LC) { 677 // FIXME: Once we implement scope handling, we want the parent region 678 // to be the scope. 679 const StackFrameContext *STC = LC->getCurrentStackFrame(); 680 assert(STC); 681 sReg = getStackLocalsRegion(STC); 682 } 683 else { 684 // We allow 'LC' to be NULL for cases where want BlockDataRegions 685 // without context-sensitivity. 686 sReg = getUnknownRegion(); 687 } 688 689 return getSubRegion<BlockDataRegion>(BC, LC, sReg); 690 } 691 692 const CompoundLiteralRegion* 693 MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL, 694 const LocationContext *LC) { 695 696 const MemRegion *sReg = 0; 697 698 if (CL->isFileScope()) 699 sReg = getGlobalsRegion(); 700 else { 701 const StackFrameContext *STC = LC->getCurrentStackFrame(); 702 assert(STC); 703 sReg = getStackLocalsRegion(STC); 704 } 705 706 return getSubRegion<CompoundLiteralRegion>(CL, sReg); 707 } 708 709 const ElementRegion* 710 MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx, 711 const MemRegion* superRegion, 712 ASTContext &Ctx){ 713 714 QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType(); 715 716 llvm::FoldingSetNodeID ID; 717 ElementRegion::ProfileRegion(ID, T, Idx, superRegion); 718 719 void *InsertPos; 720 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); 721 ElementRegion* R = cast_or_null<ElementRegion>(data); 722 723 if (!R) { 724 R = (ElementRegion*) A.Allocate<ElementRegion>(); 725 new (R) ElementRegion(T, Idx, superRegion); 726 Regions.InsertNode(R, InsertPos); 727 } 728 729 return R; 730 } 731 732 const FunctionTextRegion * 733 MemRegionManager::getFunctionTextRegion(const FunctionDecl *FD) { 734 return getSubRegion<FunctionTextRegion>(FD, getCodeRegion()); 735 } 736 737 const BlockTextRegion * 738 MemRegionManager::getBlockTextRegion(const BlockDecl *BD, CanQualType locTy, 739 AnalysisDeclContext *AC) { 740 return getSubRegion<BlockTextRegion>(BD, locTy, AC, getCodeRegion()); 741 } 742 743 744 /// getSymbolicRegion - Retrieve or create a "symbolic" memory region. 745 const SymbolicRegion *MemRegionManager::getSymbolicRegion(SymbolRef sym) { 746 return getSubRegion<SymbolicRegion>(sym, getUnknownRegion()); 747 } 748 749 const FieldRegion* 750 MemRegionManager::getFieldRegion(const FieldDecl *d, 751 const MemRegion* superRegion){ 752 return getSubRegion<FieldRegion>(d, superRegion); 753 } 754 755 const ObjCIvarRegion* 756 MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl *d, 757 const MemRegion* superRegion) { 758 return getSubRegion<ObjCIvarRegion>(d, superRegion); 759 } 760 761 const CXXTempObjectRegion* 762 MemRegionManager::getCXXTempObjectRegion(Expr const *E, 763 LocationContext const *LC) { 764 const StackFrameContext *SFC = LC->getCurrentStackFrame(); 765 assert(SFC); 766 return getSubRegion<CXXTempObjectRegion>(E, getStackLocalsRegion(SFC)); 767 } 768 769 const CXXBaseObjectRegion * 770 MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *decl, 771 const MemRegion *superRegion) { 772 return getSubRegion<CXXBaseObjectRegion>(decl, superRegion); 773 } 774 775 const CXXThisRegion* 776 MemRegionManager::getCXXThisRegion(QualType thisPointerTy, 777 const LocationContext *LC) { 778 const StackFrameContext *STC = LC->getCurrentStackFrame(); 779 assert(STC); 780 const PointerType *PT = thisPointerTy->getAs<PointerType>(); 781 assert(PT); 782 return getSubRegion<CXXThisRegion>(PT, getStackArgumentsRegion(STC)); 783 } 784 785 const AllocaRegion* 786 MemRegionManager::getAllocaRegion(const Expr *E, unsigned cnt, 787 const LocationContext *LC) { 788 const StackFrameContext *STC = LC->getCurrentStackFrame(); 789 assert(STC); 790 return getSubRegion<AllocaRegion>(E, cnt, getStackLocalsRegion(STC)); 791 } 792 793 const MemSpaceRegion *MemRegion::getMemorySpace() const { 794 const MemRegion *R = this; 795 const SubRegion* SR = dyn_cast<SubRegion>(this); 796 797 while (SR) { 798 R = SR->getSuperRegion(); 799 SR = dyn_cast<SubRegion>(R); 800 } 801 802 return dyn_cast<MemSpaceRegion>(R); 803 } 804 805 bool MemRegion::hasStackStorage() const { 806 return isa<StackSpaceRegion>(getMemorySpace()); 807 } 808 809 bool MemRegion::hasStackNonParametersStorage() const { 810 return isa<StackLocalsSpaceRegion>(getMemorySpace()); 811 } 812 813 bool MemRegion::hasStackParametersStorage() const { 814 return isa<StackArgumentsSpaceRegion>(getMemorySpace()); 815 } 816 817 bool MemRegion::hasGlobalsOrParametersStorage() const { 818 const MemSpaceRegion *MS = getMemorySpace(); 819 return isa<StackArgumentsSpaceRegion>(MS) || 820 isa<GlobalsSpaceRegion>(MS); 821 } 822 823 // getBaseRegion strips away all elements and fields, and get the base region 824 // of them. 825 const MemRegion *MemRegion::getBaseRegion() const { 826 const MemRegion *R = this; 827 while (true) { 828 switch (R->getKind()) { 829 case MemRegion::ElementRegionKind: 830 case MemRegion::FieldRegionKind: 831 case MemRegion::ObjCIvarRegionKind: 832 case MemRegion::CXXBaseObjectRegionKind: 833 R = cast<SubRegion>(R)->getSuperRegion(); 834 continue; 835 default: 836 break; 837 } 838 break; 839 } 840 return R; 841 } 842 843 //===----------------------------------------------------------------------===// 844 // View handling. 845 //===----------------------------------------------------------------------===// 846 847 const MemRegion *MemRegion::StripCasts() const { 848 const MemRegion *R = this; 849 while (true) { 850 if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { 851 // FIXME: generalize. Essentially we want to strip away ElementRegions 852 // that were layered on a symbolic region because of casts. We only 853 // want to strip away ElementRegions, however, where the index is 0. 854 SVal index = ER->getIndex(); 855 if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&index)) { 856 if (CI->getValue().getSExtValue() == 0) { 857 R = ER->getSuperRegion(); 858 continue; 859 } 860 } 861 } 862 break; 863 } 864 return R; 865 } 866 867 // FIXME: Merge with the implementation of the same method in Store.cpp 868 static bool IsCompleteType(ASTContext &Ctx, QualType Ty) { 869 if (const RecordType *RT = Ty->getAs<RecordType>()) { 870 const RecordDecl *D = RT->getDecl(); 871 if (!D->getDefinition()) 872 return false; 873 } 874 875 return true; 876 } 877 878 RegionRawOffset ElementRegion::getAsArrayOffset() const { 879 CharUnits offset = CharUnits::Zero(); 880 const ElementRegion *ER = this; 881 const MemRegion *superR = NULL; 882 ASTContext &C = getContext(); 883 884 // FIXME: Handle multi-dimensional arrays. 885 886 while (ER) { 887 superR = ER->getSuperRegion(); 888 889 // FIXME: generalize to symbolic offsets. 890 SVal index = ER->getIndex(); 891 if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&index)) { 892 // Update the offset. 893 int64_t i = CI->getValue().getSExtValue(); 894 895 if (i != 0) { 896 QualType elemType = ER->getElementType(); 897 898 // If we are pointing to an incomplete type, go no further. 899 if (!IsCompleteType(C, elemType)) { 900 superR = ER; 901 break; 902 } 903 904 CharUnits size = C.getTypeSizeInChars(elemType); 905 offset += (i * size); 906 } 907 908 // Go to the next ElementRegion (if any). 909 ER = dyn_cast<ElementRegion>(superR); 910 continue; 911 } 912 913 return NULL; 914 } 915 916 assert(superR && "super region cannot be NULL"); 917 return RegionRawOffset(superR, offset); 918 } 919 920 RegionOffset MemRegion::getAsOffset() const { 921 const MemRegion *R = this; 922 int64_t Offset = 0; 923 924 while (1) { 925 switch (R->getKind()) { 926 default: 927 return RegionOffset(0); 928 case SymbolicRegionKind: 929 case AllocaRegionKind: 930 case CompoundLiteralRegionKind: 931 case CXXThisRegionKind: 932 case StringRegionKind: 933 case VarRegionKind: 934 case CXXTempObjectRegionKind: 935 goto Finish; 936 case ElementRegionKind: { 937 const ElementRegion *ER = cast<ElementRegion>(R); 938 QualType EleTy = ER->getValueType(); 939 940 if (!IsCompleteType(getContext(), EleTy)) 941 return RegionOffset(0); 942 943 SVal Index = ER->getIndex(); 944 if (const nonloc::ConcreteInt *CI=dyn_cast<nonloc::ConcreteInt>(&Index)) { 945 int64_t i = CI->getValue().getSExtValue(); 946 CharUnits Size = getContext().getTypeSizeInChars(EleTy); 947 Offset += i * Size.getQuantity() * 8; 948 } else { 949 // We cannot compute offset for non-concrete index. 950 return RegionOffset(0); 951 } 952 R = ER->getSuperRegion(); 953 break; 954 } 955 case FieldRegionKind: { 956 const FieldRegion *FR = cast<FieldRegion>(R); 957 const RecordDecl *RD = FR->getDecl()->getParent(); 958 if (!RD->isCompleteDefinition()) 959 // We cannot compute offset for incomplete type. 960 return RegionOffset(0); 961 // Get the field number. 962 unsigned idx = 0; 963 for (RecordDecl::field_iterator FI = RD->field_begin(), 964 FE = RD->field_end(); FI != FE; ++FI, ++idx) 965 if (FR->getDecl() == *FI) 966 break; 967 968 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); 969 // This is offset in bits. 970 Offset += Layout.getFieldOffset(idx); 971 R = FR->getSuperRegion(); 972 break; 973 } 974 } 975 } 976 977 Finish: 978 return RegionOffset(R, Offset); 979 } 980 981 //===----------------------------------------------------------------------===// 982 // BlockDataRegion 983 //===----------------------------------------------------------------------===// 984 985 void BlockDataRegion::LazyInitializeReferencedVars() { 986 if (ReferencedVars) 987 return; 988 989 AnalysisDeclContext *AC = getCodeRegion()->getAnalysisDeclContext(); 990 AnalysisDeclContext::referenced_decls_iterator I, E; 991 llvm::tie(I, E) = AC->getReferencedBlockVars(BC->getDecl()); 992 993 if (I == E) { 994 ReferencedVars = (void*) 0x1; 995 return; 996 } 997 998 MemRegionManager &MemMgr = *getMemRegionManager(); 999 llvm::BumpPtrAllocator &A = MemMgr.getAllocator(); 1000 BumpVectorContext BC(A); 1001 1002 typedef BumpVector<const MemRegion*> VarVec; 1003 VarVec *BV = (VarVec*) A.Allocate<VarVec>(); 1004 new (BV) VarVec(BC, E - I); 1005 1006 for ( ; I != E; ++I) { 1007 const VarDecl *VD = *I; 1008 const VarRegion *VR = 0; 1009 1010 if (!VD->getAttr<BlocksAttr>() && VD->hasLocalStorage()) 1011 VR = MemMgr.getVarRegion(VD, this); 1012 else { 1013 if (LC) 1014 VR = MemMgr.getVarRegion(VD, LC); 1015 else { 1016 VR = MemMgr.getVarRegion(VD, MemMgr.getUnknownRegion()); 1017 } 1018 } 1019 1020 assert(VR); 1021 BV->push_back(VR, BC); 1022 } 1023 1024 ReferencedVars = BV; 1025 } 1026 1027 BlockDataRegion::referenced_vars_iterator 1028 BlockDataRegion::referenced_vars_begin() const { 1029 const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars(); 1030 1031 BumpVector<const MemRegion*> *Vec = 1032 static_cast<BumpVector<const MemRegion*>*>(ReferencedVars); 1033 1034 return BlockDataRegion::referenced_vars_iterator(Vec == (void*) 0x1 ? 1035 NULL : Vec->begin()); 1036 } 1037 1038 BlockDataRegion::referenced_vars_iterator 1039 BlockDataRegion::referenced_vars_end() const { 1040 const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars(); 1041 1042 BumpVector<const MemRegion*> *Vec = 1043 static_cast<BumpVector<const MemRegion*>*>(ReferencedVars); 1044 1045 return BlockDataRegion::referenced_vars_iterator(Vec == (void*) 0x1 ? 1046 NULL : Vec->end()); 1047 } 1048