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/AST/Attr.h" 18 #include "clang/AST/CharUnits.h" 19 #include "clang/AST/DeclObjC.h" 20 #include "clang/AST/RecordLayout.h" 21 #include "clang/Analysis/AnalysisContext.h" 22 #include "clang/Analysis/Support/BumpVector.h" 23 #include "clang/Basic/SourceManager.h" 24 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" 25 #include "llvm/Support/raw_ostream.h" 26 27 using namespace clang; 28 using namespace ento; 29 30 //===----------------------------------------------------------------------===// 31 // MemRegion Construction. 32 //===----------------------------------------------------------------------===// 33 34 template <typename RegionTy, typename SuperTy, typename Arg1Ty> 35 RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, 36 const SuperTy *superRegion) { 37 llvm::FoldingSetNodeID ID; 38 RegionTy::ProfileRegion(ID, arg1, superRegion); 39 void *InsertPos; 40 RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, 41 InsertPos)); 42 43 if (!R) { 44 R = A.Allocate<RegionTy>(); 45 new (R) RegionTy(arg1, superRegion); 46 Regions.InsertNode(R, InsertPos); 47 } 48 49 return R; 50 } 51 52 template <typename RegionTy, typename SuperTy, typename Arg1Ty, typename Arg2Ty> 53 RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, 54 const SuperTy *superRegion) { 55 llvm::FoldingSetNodeID ID; 56 RegionTy::ProfileRegion(ID, arg1, arg2, superRegion); 57 void *InsertPos; 58 RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, 59 InsertPos)); 60 61 if (!R) { 62 R = A.Allocate<RegionTy>(); 63 new (R) RegionTy(arg1, arg2, superRegion); 64 Regions.InsertNode(R, InsertPos); 65 } 66 67 return R; 68 } 69 70 template <typename RegionTy, typename SuperTy, 71 typename Arg1Ty, typename Arg2Ty, typename Arg3Ty> 72 RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, 73 const Arg3Ty arg3, 74 const SuperTy *superRegion) { 75 llvm::FoldingSetNodeID ID; 76 RegionTy::ProfileRegion(ID, arg1, arg2, arg3, superRegion); 77 void *InsertPos; 78 RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, 79 InsertPos)); 80 81 if (!R) { 82 R = A.Allocate<RegionTy>(); 83 new (R) RegionTy(arg1, arg2, arg3, superRegion); 84 Regions.InsertNode(R, InsertPos); 85 } 86 87 return R; 88 } 89 90 //===----------------------------------------------------------------------===// 91 // Object destruction. 92 //===----------------------------------------------------------------------===// 93 94 MemRegion::~MemRegion() {} 95 96 MemRegionManager::~MemRegionManager() { 97 // All regions and their data are BumpPtrAllocated. No need to call 98 // their destructors. 99 } 100 101 //===----------------------------------------------------------------------===// 102 // Basic methods. 103 //===----------------------------------------------------------------------===// 104 105 bool SubRegion::isSubRegionOf(const MemRegion* R) const { 106 const MemRegion* r = getSuperRegion(); 107 while (r != nullptr) { 108 if (r == R) 109 return true; 110 if (const SubRegion* sr = dyn_cast<SubRegion>(r)) 111 r = sr->getSuperRegion(); 112 else 113 break; 114 } 115 return false; 116 } 117 118 MemRegionManager* SubRegion::getMemRegionManager() const { 119 const SubRegion* r = this; 120 do { 121 const MemRegion *superRegion = r->getSuperRegion(); 122 if (const SubRegion *sr = dyn_cast<SubRegion>(superRegion)) { 123 r = sr; 124 continue; 125 } 126 return superRegion->getMemRegionManager(); 127 } while (1); 128 } 129 130 const StackFrameContext *VarRegion::getStackFrame() const { 131 const StackSpaceRegion *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace()); 132 return SSR ? SSR->getStackFrame() : nullptr; 133 } 134 135 //===----------------------------------------------------------------------===// 136 // Region extents. 137 //===----------------------------------------------------------------------===// 138 139 DefinedOrUnknownSVal TypedValueRegion::getExtent(SValBuilder &svalBuilder) const { 140 ASTContext &Ctx = svalBuilder.getContext(); 141 QualType T = getDesugaredValueType(Ctx); 142 143 if (isa<VariableArrayType>(T)) 144 return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this)); 145 if (T->isIncompleteType()) 146 return UnknownVal(); 147 148 CharUnits size = Ctx.getTypeSizeInChars(T); 149 QualType sizeTy = svalBuilder.getArrayIndexType(); 150 return svalBuilder.makeIntVal(size.getQuantity(), sizeTy); 151 } 152 153 DefinedOrUnknownSVal FieldRegion::getExtent(SValBuilder &svalBuilder) const { 154 // Force callers to deal with bitfields explicitly. 155 if (getDecl()->isBitField()) 156 return UnknownVal(); 157 158 DefinedOrUnknownSVal Extent = DeclRegion::getExtent(svalBuilder); 159 160 // A zero-length array at the end of a struct often stands for dynamically- 161 // allocated extra memory. 162 if (Extent.isZeroConstant()) { 163 QualType T = getDesugaredValueType(svalBuilder.getContext()); 164 165 if (isa<ConstantArrayType>(T)) 166 return UnknownVal(); 167 } 168 169 return Extent; 170 } 171 172 DefinedOrUnknownSVal AllocaRegion::getExtent(SValBuilder &svalBuilder) const { 173 return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this)); 174 } 175 176 DefinedOrUnknownSVal SymbolicRegion::getExtent(SValBuilder &svalBuilder) const { 177 return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this)); 178 } 179 180 DefinedOrUnknownSVal StringRegion::getExtent(SValBuilder &svalBuilder) const { 181 return svalBuilder.makeIntVal(getStringLiteral()->getByteLength()+1, 182 svalBuilder.getArrayIndexType()); 183 } 184 185 ObjCIvarRegion::ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg) 186 : DeclRegion(ivd, sReg, ObjCIvarRegionKind) {} 187 188 const ObjCIvarDecl *ObjCIvarRegion::getDecl() const { 189 return cast<ObjCIvarDecl>(D); 190 } 191 192 QualType ObjCIvarRegion::getValueType() const { 193 return getDecl()->getType(); 194 } 195 196 QualType CXXBaseObjectRegion::getValueType() const { 197 return QualType(getDecl()->getTypeForDecl(), 0); 198 } 199 200 //===----------------------------------------------------------------------===// 201 // FoldingSet profiling. 202 //===----------------------------------------------------------------------===// 203 204 void MemSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const { 205 ID.AddInteger(static_cast<unsigned>(getKind())); 206 } 207 208 void StackSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const { 209 ID.AddInteger(static_cast<unsigned>(getKind())); 210 ID.AddPointer(getStackFrame()); 211 } 212 213 void StaticGlobalSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const { 214 ID.AddInteger(static_cast<unsigned>(getKind())); 215 ID.AddPointer(getCodeRegion()); 216 } 217 218 void StringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 219 const StringLiteral* Str, 220 const MemRegion* superRegion) { 221 ID.AddInteger(static_cast<unsigned>(StringRegionKind)); 222 ID.AddPointer(Str); 223 ID.AddPointer(superRegion); 224 } 225 226 void ObjCStringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 227 const ObjCStringLiteral* Str, 228 const MemRegion* superRegion) { 229 ID.AddInteger(static_cast<unsigned>(ObjCStringRegionKind)); 230 ID.AddPointer(Str); 231 ID.AddPointer(superRegion); 232 } 233 234 void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 235 const Expr *Ex, unsigned cnt, 236 const MemRegion *superRegion) { 237 ID.AddInteger(static_cast<unsigned>(AllocaRegionKind)); 238 ID.AddPointer(Ex); 239 ID.AddInteger(cnt); 240 ID.AddPointer(superRegion); 241 } 242 243 void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const { 244 ProfileRegion(ID, Ex, Cnt, superRegion); 245 } 246 247 void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const { 248 CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion); 249 } 250 251 void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 252 const CompoundLiteralExpr *CL, 253 const MemRegion* superRegion) { 254 ID.AddInteger(static_cast<unsigned>(CompoundLiteralRegionKind)); 255 ID.AddPointer(CL); 256 ID.AddPointer(superRegion); 257 } 258 259 void CXXThisRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, 260 const PointerType *PT, 261 const MemRegion *sRegion) { 262 ID.AddInteger(static_cast<unsigned>(CXXThisRegionKind)); 263 ID.AddPointer(PT); 264 ID.AddPointer(sRegion); 265 } 266 267 void CXXThisRegion::Profile(llvm::FoldingSetNodeID &ID) const { 268 CXXThisRegion::ProfileRegion(ID, ThisPointerTy, superRegion); 269 } 270 271 void ObjCIvarRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 272 const ObjCIvarDecl *ivd, 273 const MemRegion* superRegion) { 274 DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCIvarRegionKind); 275 } 276 277 void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D, 278 const MemRegion* superRegion, Kind k) { 279 ID.AddInteger(static_cast<unsigned>(k)); 280 ID.AddPointer(D); 281 ID.AddPointer(superRegion); 282 } 283 284 void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const { 285 DeclRegion::ProfileRegion(ID, D, superRegion, getKind()); 286 } 287 288 void VarRegion::Profile(llvm::FoldingSetNodeID &ID) const { 289 VarRegion::ProfileRegion(ID, getDecl(), superRegion); 290 } 291 292 void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym, 293 const MemRegion *sreg) { 294 ID.AddInteger(static_cast<unsigned>(MemRegion::SymbolicRegionKind)); 295 ID.Add(sym); 296 ID.AddPointer(sreg); 297 } 298 299 void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const { 300 SymbolicRegion::ProfileRegion(ID, sym, getSuperRegion()); 301 } 302 303 void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 304 QualType ElementType, SVal Idx, 305 const MemRegion* superRegion) { 306 ID.AddInteger(MemRegion::ElementRegionKind); 307 ID.Add(ElementType); 308 ID.AddPointer(superRegion); 309 Idx.Profile(ID); 310 } 311 312 void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const { 313 ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion); 314 } 315 316 void FunctionCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 317 const NamedDecl *FD, 318 const MemRegion*) { 319 ID.AddInteger(MemRegion::FunctionCodeRegionKind); 320 ID.AddPointer(FD); 321 } 322 323 void FunctionCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const { 324 FunctionCodeRegion::ProfileRegion(ID, FD, superRegion); 325 } 326 327 void BlockCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 328 const BlockDecl *BD, CanQualType, 329 const AnalysisDeclContext *AC, 330 const MemRegion*) { 331 ID.AddInteger(MemRegion::BlockCodeRegionKind); 332 ID.AddPointer(BD); 333 } 334 335 void BlockCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const { 336 BlockCodeRegion::ProfileRegion(ID, BD, locTy, AC, superRegion); 337 } 338 339 void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 340 const BlockCodeRegion *BC, 341 const LocationContext *LC, 342 unsigned BlkCount, 343 const MemRegion *sReg) { 344 ID.AddInteger(MemRegion::BlockDataRegionKind); 345 ID.AddPointer(BC); 346 ID.AddPointer(LC); 347 ID.AddInteger(BlkCount); 348 ID.AddPointer(sReg); 349 } 350 351 void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const { 352 BlockDataRegion::ProfileRegion(ID, BC, LC, BlockCount, getSuperRegion()); 353 } 354 355 void CXXTempObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, 356 Expr const *Ex, 357 const MemRegion *sReg) { 358 ID.AddPointer(Ex); 359 ID.AddPointer(sReg); 360 } 361 362 void CXXTempObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { 363 ProfileRegion(ID, Ex, getSuperRegion()); 364 } 365 366 void CXXBaseObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, 367 const CXXRecordDecl *RD, 368 bool IsVirtual, 369 const MemRegion *SReg) { 370 ID.AddPointer(RD); 371 ID.AddBoolean(IsVirtual); 372 ID.AddPointer(SReg); 373 } 374 375 void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { 376 ProfileRegion(ID, getDecl(), isVirtual(), superRegion); 377 } 378 379 //===----------------------------------------------------------------------===// 380 // Region anchors. 381 //===----------------------------------------------------------------------===// 382 383 void GlobalsSpaceRegion::anchor() { } 384 void NonStaticGlobalSpaceRegion::anchor() { } 385 void StackSpaceRegion::anchor() { } 386 void TypedRegion::anchor() { } 387 void TypedValueRegion::anchor() { } 388 void CodeTextRegion::anchor() { } 389 void SubRegion::anchor() { } 390 391 //===----------------------------------------------------------------------===// 392 // Region pretty-printing. 393 //===----------------------------------------------------------------------===// 394 395 LLVM_DUMP_METHOD void MemRegion::dump() const { 396 dumpToStream(llvm::errs()); 397 } 398 399 std::string MemRegion::getString() const { 400 std::string s; 401 llvm::raw_string_ostream os(s); 402 dumpToStream(os); 403 return os.str(); 404 } 405 406 void MemRegion::dumpToStream(raw_ostream &os) const { 407 os << "<Unknown Region>"; 408 } 409 410 void AllocaRegion::dumpToStream(raw_ostream &os) const { 411 os << "alloca{" << static_cast<const void*>(Ex) << ',' << Cnt << '}'; 412 } 413 414 void FunctionCodeRegion::dumpToStream(raw_ostream &os) const { 415 os << "code{" << getDecl()->getDeclName().getAsString() << '}'; 416 } 417 418 void BlockCodeRegion::dumpToStream(raw_ostream &os) const { 419 os << "block_code{" << static_cast<const void*>(this) << '}'; 420 } 421 422 void BlockDataRegion::dumpToStream(raw_ostream &os) const { 423 os << "block_data{" << BC; 424 os << "; "; 425 for (BlockDataRegion::referenced_vars_iterator 426 I = referenced_vars_begin(), 427 E = referenced_vars_end(); I != E; ++I) 428 os << "(" << I.getCapturedRegion() << "," << 429 I.getOriginalRegion() << ") "; 430 os << '}'; 431 } 432 433 void CompoundLiteralRegion::dumpToStream(raw_ostream &os) const { 434 // FIXME: More elaborate pretty-printing. 435 os << "{ " << static_cast<const void*>(CL) << " }"; 436 } 437 438 void CXXTempObjectRegion::dumpToStream(raw_ostream &os) const { 439 os << "temp_object{" << getValueType().getAsString() << ',' 440 << static_cast<const void*>(Ex) << '}'; 441 } 442 443 void CXXBaseObjectRegion::dumpToStream(raw_ostream &os) const { 444 os << "base{" << superRegion << ',' << getDecl()->getName() << '}'; 445 } 446 447 void CXXThisRegion::dumpToStream(raw_ostream &os) const { 448 os << "this"; 449 } 450 451 void ElementRegion::dumpToStream(raw_ostream &os) const { 452 os << "element{" << superRegion << ',' 453 << Index << ',' << getElementType().getAsString() << '}'; 454 } 455 456 void FieldRegion::dumpToStream(raw_ostream &os) const { 457 os << superRegion << "->" << *getDecl(); 458 } 459 460 void ObjCIvarRegion::dumpToStream(raw_ostream &os) const { 461 os << "ivar{" << superRegion << ',' << *getDecl() << '}'; 462 } 463 464 void StringRegion::dumpToStream(raw_ostream &os) const { 465 assert(Str != nullptr && "Expecting non-null StringLiteral"); 466 Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts())); 467 } 468 469 void ObjCStringRegion::dumpToStream(raw_ostream &os) const { 470 assert(Str != nullptr && "Expecting non-null ObjCStringLiteral"); 471 Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts())); 472 } 473 474 void SymbolicRegion::dumpToStream(raw_ostream &os) const { 475 os << "SymRegion{" << sym << '}'; 476 } 477 478 void VarRegion::dumpToStream(raw_ostream &os) const { 479 os << *cast<VarDecl>(D); 480 } 481 482 LLVM_DUMP_METHOD void RegionRawOffset::dump() const { 483 dumpToStream(llvm::errs()); 484 } 485 486 void RegionRawOffset::dumpToStream(raw_ostream &os) const { 487 os << "raw_offset{" << getRegion() << ',' << getOffset().getQuantity() << '}'; 488 } 489 490 void CodeSpaceRegion::dumpToStream(raw_ostream &os) const { 491 os << "CodeSpaceRegion"; 492 } 493 494 void StaticGlobalSpaceRegion::dumpToStream(raw_ostream &os) const { 495 os << "StaticGlobalsMemSpace{" << CR << '}'; 496 } 497 498 void GlobalInternalSpaceRegion::dumpToStream(raw_ostream &os) const { 499 os << "GlobalInternalSpaceRegion"; 500 } 501 502 void GlobalSystemSpaceRegion::dumpToStream(raw_ostream &os) const { 503 os << "GlobalSystemSpaceRegion"; 504 } 505 506 void GlobalImmutableSpaceRegion::dumpToStream(raw_ostream &os) const { 507 os << "GlobalImmutableSpaceRegion"; 508 } 509 510 void HeapSpaceRegion::dumpToStream(raw_ostream &os) const { 511 os << "HeapSpaceRegion"; 512 } 513 514 void UnknownSpaceRegion::dumpToStream(raw_ostream &os) const { 515 os << "UnknownSpaceRegion"; 516 } 517 518 void StackArgumentsSpaceRegion::dumpToStream(raw_ostream &os) const { 519 os << "StackArgumentsSpaceRegion"; 520 } 521 522 void StackLocalsSpaceRegion::dumpToStream(raw_ostream &os) const { 523 os << "StackLocalsSpaceRegion"; 524 } 525 526 bool MemRegion::canPrintPretty() const { 527 return canPrintPrettyAsExpr(); 528 } 529 530 bool MemRegion::canPrintPrettyAsExpr() const { 531 return false; 532 } 533 534 void MemRegion::printPretty(raw_ostream &os) const { 535 assert(canPrintPretty() && "This region cannot be printed pretty."); 536 os << "'"; 537 printPrettyAsExpr(os); 538 os << "'"; 539 } 540 541 void MemRegion::printPrettyAsExpr(raw_ostream &os) const { 542 llvm_unreachable("This region cannot be printed pretty."); 543 } 544 545 bool VarRegion::canPrintPrettyAsExpr() const { 546 return true; 547 } 548 549 void VarRegion::printPrettyAsExpr(raw_ostream &os) const { 550 os << getDecl()->getName(); 551 } 552 553 bool ObjCIvarRegion::canPrintPrettyAsExpr() const { 554 return true; 555 } 556 557 void ObjCIvarRegion::printPrettyAsExpr(raw_ostream &os) const { 558 os << getDecl()->getName(); 559 } 560 561 bool FieldRegion::canPrintPretty() const { 562 return true; 563 } 564 565 bool FieldRegion::canPrintPrettyAsExpr() const { 566 return superRegion->canPrintPrettyAsExpr(); 567 } 568 569 void FieldRegion::printPrettyAsExpr(raw_ostream &os) const { 570 assert(canPrintPrettyAsExpr()); 571 superRegion->printPrettyAsExpr(os); 572 os << "." << getDecl()->getName(); 573 } 574 575 void FieldRegion::printPretty(raw_ostream &os) const { 576 if (canPrintPrettyAsExpr()) { 577 os << "\'"; 578 printPrettyAsExpr(os); 579 os << "'"; 580 } else { 581 os << "field " << "\'" << getDecl()->getName() << "'"; 582 } 583 } 584 585 bool CXXBaseObjectRegion::canPrintPrettyAsExpr() const { 586 return superRegion->canPrintPrettyAsExpr(); 587 } 588 589 void CXXBaseObjectRegion::printPrettyAsExpr(raw_ostream &os) const { 590 superRegion->printPrettyAsExpr(os); 591 } 592 593 std::string MemRegion::getDescriptiveName(bool UseQuotes) const { 594 std::string VariableName; 595 std::string ArrayIndices; 596 const MemRegion *R = this; 597 SmallString<50> buf; 598 llvm::raw_svector_ostream os(buf); 599 600 // Obtain array indices to add them to the variable name. 601 const ElementRegion *ER = nullptr; 602 while ((ER = R->getAs<ElementRegion>())) { 603 // Index is a ConcreteInt. 604 if (auto CI = ER->getIndex().getAs<nonloc::ConcreteInt>()) { 605 llvm::SmallString<2> Idx; 606 CI->getValue().toString(Idx); 607 ArrayIndices = (llvm::Twine("[") + Idx.str() + "]" + ArrayIndices).str(); 608 } 609 // If not a ConcreteInt, try to obtain the variable 610 // name by calling 'getDescriptiveName' recursively. 611 else { 612 std::string Idx = ER->getDescriptiveName(false); 613 if (!Idx.empty()) { 614 ArrayIndices = (llvm::Twine("[") + Idx + "]" + ArrayIndices).str(); 615 } 616 } 617 R = ER->getSuperRegion(); 618 } 619 620 // Get variable name. 621 if (R && R->canPrintPrettyAsExpr()) { 622 R->printPrettyAsExpr(os); 623 if (UseQuotes) { 624 return (llvm::Twine("'") + os.str() + ArrayIndices + "'").str(); 625 } else { 626 return (llvm::Twine(os.str()) + ArrayIndices).str(); 627 } 628 } 629 630 return VariableName; 631 } 632 633 SourceRange MemRegion::sourceRange() const { 634 const VarRegion *const VR = dyn_cast<VarRegion>(this->getBaseRegion()); 635 const FieldRegion *const FR = dyn_cast<FieldRegion>(this); 636 637 // Check for more specific regions first. 638 // FieldRegion 639 if (FR) { 640 return FR->getDecl()->getSourceRange(); 641 } 642 // VarRegion 643 else if (VR) { 644 return VR->getDecl()->getSourceRange(); 645 } 646 // Return invalid source range (can be checked by client). 647 else { 648 return SourceRange{}; 649 } 650 } 651 652 //===----------------------------------------------------------------------===// 653 // MemRegionManager methods. 654 //===----------------------------------------------------------------------===// 655 656 template <typename REG> 657 const REG *MemRegionManager::LazyAllocate(REG*& region) { 658 if (!region) { 659 region = A.Allocate<REG>(); 660 new (region) REG(this); 661 } 662 663 return region; 664 } 665 666 template <typename REG, typename ARG> 667 const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) { 668 if (!region) { 669 region = A.Allocate<REG>(); 670 new (region) REG(this, a); 671 } 672 673 return region; 674 } 675 676 const StackLocalsSpaceRegion* 677 MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) { 678 assert(STC); 679 StackLocalsSpaceRegion *&R = StackLocalsSpaceRegions[STC]; 680 681 if (R) 682 return R; 683 684 R = A.Allocate<StackLocalsSpaceRegion>(); 685 new (R) StackLocalsSpaceRegion(this, STC); 686 return R; 687 } 688 689 const StackArgumentsSpaceRegion * 690 MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) { 691 assert(STC); 692 StackArgumentsSpaceRegion *&R = StackArgumentsSpaceRegions[STC]; 693 694 if (R) 695 return R; 696 697 R = A.Allocate<StackArgumentsSpaceRegion>(); 698 new (R) StackArgumentsSpaceRegion(this, STC); 699 return R; 700 } 701 702 const GlobalsSpaceRegion 703 *MemRegionManager::getGlobalsRegion(MemRegion::Kind K, 704 const CodeTextRegion *CR) { 705 if (!CR) { 706 if (K == MemRegion::GlobalSystemSpaceRegionKind) 707 return LazyAllocate(SystemGlobals); 708 if (K == MemRegion::GlobalImmutableSpaceRegionKind) 709 return LazyAllocate(ImmutableGlobals); 710 assert(K == MemRegion::GlobalInternalSpaceRegionKind); 711 return LazyAllocate(InternalGlobals); 712 } 713 714 assert(K == MemRegion::StaticGlobalSpaceRegionKind); 715 StaticGlobalSpaceRegion *&R = StaticsGlobalSpaceRegions[CR]; 716 if (R) 717 return R; 718 719 R = A.Allocate<StaticGlobalSpaceRegion>(); 720 new (R) StaticGlobalSpaceRegion(this, CR); 721 return R; 722 } 723 724 const HeapSpaceRegion *MemRegionManager::getHeapRegion() { 725 return LazyAllocate(heap); 726 } 727 728 const UnknownSpaceRegion *MemRegionManager::getUnknownRegion() { 729 return LazyAllocate(unknown); 730 } 731 732 const CodeSpaceRegion *MemRegionManager::getCodeRegion() { 733 return LazyAllocate(code); 734 } 735 736 //===----------------------------------------------------------------------===// 737 // Constructing regions. 738 //===----------------------------------------------------------------------===// 739 const StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str){ 740 return getSubRegion<StringRegion>( 741 Str, cast<GlobalInternalSpaceRegion>(getGlobalsRegion())); 742 } 743 744 const ObjCStringRegion * 745 MemRegionManager::getObjCStringRegion(const ObjCStringLiteral* Str){ 746 return getSubRegion<ObjCStringRegion>( 747 Str, cast<GlobalInternalSpaceRegion>(getGlobalsRegion())); 748 } 749 750 /// Look through a chain of LocationContexts to either find the 751 /// StackFrameContext that matches a DeclContext, or find a VarRegion 752 /// for a variable captured by a block. 753 static llvm::PointerUnion<const StackFrameContext *, const VarRegion *> 754 getStackOrCaptureRegionForDeclContext(const LocationContext *LC, 755 const DeclContext *DC, 756 const VarDecl *VD) { 757 while (LC) { 758 if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC)) { 759 if (cast<DeclContext>(SFC->getDecl()) == DC) 760 return SFC; 761 } 762 if (const BlockInvocationContext *BC = 763 dyn_cast<BlockInvocationContext>(LC)) { 764 const BlockDataRegion *BR = 765 static_cast<const BlockDataRegion*>(BC->getContextData()); 766 // FIXME: This can be made more efficient. 767 for (BlockDataRegion::referenced_vars_iterator 768 I = BR->referenced_vars_begin(), 769 E = BR->referenced_vars_end(); I != E; ++I) { 770 if (const VarRegion *VR = dyn_cast<VarRegion>(I.getOriginalRegion())) 771 if (VR->getDecl() == VD) 772 return cast<VarRegion>(I.getCapturedRegion()); 773 } 774 } 775 776 LC = LC->getParent(); 777 } 778 return (const StackFrameContext *)nullptr; 779 } 780 781 const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D, 782 const LocationContext *LC) { 783 const MemRegion *sReg = nullptr; 784 785 if (D->hasGlobalStorage() && !D->isStaticLocal()) { 786 787 // First handle the globals defined in system headers. 788 if (C.getSourceManager().isInSystemHeader(D->getLocation())) { 789 // Whitelist the system globals which often DO GET modified, assume the 790 // rest are immutable. 791 if (D->getName().find("errno") != StringRef::npos) 792 sReg = getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind); 793 else 794 sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); 795 796 // Treat other globals as GlobalInternal unless they are constants. 797 } else { 798 QualType GQT = D->getType(); 799 const Type *GT = GQT.getTypePtrOrNull(); 800 // TODO: We could walk the complex types here and see if everything is 801 // constified. 802 if (GT && GQT.isConstQualified() && GT->isArithmeticType()) 803 sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); 804 else 805 sReg = getGlobalsRegion(); 806 } 807 808 // Finally handle static locals. 809 } else { 810 // FIXME: Once we implement scope handling, we will need to properly lookup 811 // 'D' to the proper LocationContext. 812 const DeclContext *DC = D->getDeclContext(); 813 llvm::PointerUnion<const StackFrameContext *, const VarRegion *> V = 814 getStackOrCaptureRegionForDeclContext(LC, DC, D); 815 816 if (V.is<const VarRegion*>()) 817 return V.get<const VarRegion*>(); 818 819 const StackFrameContext *STC = V.get<const StackFrameContext*>(); 820 821 if (!STC) { 822 // FIXME: Assign a more sensible memory space to static locals 823 // we see from within blocks that we analyze as top-level declarations. 824 sReg = getUnknownRegion(); 825 } else { 826 if (D->hasLocalStorage()) { 827 sReg = isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) 828 ? static_cast<const MemRegion*>(getStackArgumentsRegion(STC)) 829 : static_cast<const MemRegion*>(getStackLocalsRegion(STC)); 830 } 831 else { 832 assert(D->isStaticLocal()); 833 const Decl *STCD = STC->getDecl(); 834 if (isa<FunctionDecl>(STCD) || isa<ObjCMethodDecl>(STCD)) 835 sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, 836 getFunctionCodeRegion(cast<NamedDecl>(STCD))); 837 else if (const BlockDecl *BD = dyn_cast<BlockDecl>(STCD)) { 838 // FIXME: The fallback type here is totally bogus -- though it should 839 // never be queried, it will prevent uniquing with the real 840 // BlockCodeRegion. Ideally we'd fix the AST so that we always had a 841 // signature. 842 QualType T; 843 if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten()) 844 T = TSI->getType(); 845 if (T.isNull()) 846 T = getContext().VoidTy; 847 if (!T->getAs<FunctionType>()) 848 T = getContext().getFunctionNoProtoType(T); 849 T = getContext().getBlockPointerType(T); 850 851 const BlockCodeRegion *BTR = 852 getBlockCodeRegion(BD, C.getCanonicalType(T), 853 STC->getAnalysisDeclContext()); 854 sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, 855 BTR); 856 } 857 else { 858 sReg = getGlobalsRegion(); 859 } 860 } 861 } 862 } 863 864 return getSubRegion<VarRegion>(D, sReg); 865 } 866 867 const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D, 868 const MemRegion *superR) { 869 return getSubRegion<VarRegion>(D, superR); 870 } 871 872 const BlockDataRegion * 873 MemRegionManager::getBlockDataRegion(const BlockCodeRegion *BC, 874 const LocationContext *LC, 875 unsigned blockCount) { 876 const MemSpaceRegion *sReg = nullptr; 877 const BlockDecl *BD = BC->getDecl(); 878 if (!BD->hasCaptures()) { 879 // This handles 'static' blocks. 880 sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); 881 } 882 else { 883 if (LC) { 884 // FIXME: Once we implement scope handling, we want the parent region 885 // to be the scope. 886 const StackFrameContext *STC = LC->getCurrentStackFrame(); 887 assert(STC); 888 sReg = getStackLocalsRegion(STC); 889 } 890 else { 891 // We allow 'LC' to be NULL for cases where want BlockDataRegions 892 // without context-sensitivity. 893 sReg = getUnknownRegion(); 894 } 895 } 896 897 return getSubRegion<BlockDataRegion>(BC, LC, blockCount, sReg); 898 } 899 900 const CXXTempObjectRegion * 901 MemRegionManager::getCXXStaticTempObjectRegion(const Expr *Ex) { 902 return getSubRegion<CXXTempObjectRegion>( 903 Ex, getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind, nullptr)); 904 } 905 906 const CompoundLiteralRegion* 907 MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL, 908 const LocationContext *LC) { 909 const MemSpaceRegion *sReg = nullptr; 910 911 if (CL->isFileScope()) 912 sReg = getGlobalsRegion(); 913 else { 914 const StackFrameContext *STC = LC->getCurrentStackFrame(); 915 assert(STC); 916 sReg = getStackLocalsRegion(STC); 917 } 918 919 return getSubRegion<CompoundLiteralRegion>(CL, sReg); 920 } 921 922 const ElementRegion* 923 MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx, 924 const SubRegion* superRegion, 925 ASTContext &Ctx){ 926 QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType(); 927 928 llvm::FoldingSetNodeID ID; 929 ElementRegion::ProfileRegion(ID, T, Idx, superRegion); 930 931 void *InsertPos; 932 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); 933 ElementRegion* R = cast_or_null<ElementRegion>(data); 934 935 if (!R) { 936 R = A.Allocate<ElementRegion>(); 937 new (R) ElementRegion(T, Idx, superRegion); 938 Regions.InsertNode(R, InsertPos); 939 } 940 941 return R; 942 } 943 944 const FunctionCodeRegion * 945 MemRegionManager::getFunctionCodeRegion(const NamedDecl *FD) { 946 return getSubRegion<FunctionCodeRegion>(FD, getCodeRegion()); 947 } 948 949 const BlockCodeRegion * 950 MemRegionManager::getBlockCodeRegion(const BlockDecl *BD, CanQualType locTy, 951 AnalysisDeclContext *AC) { 952 return getSubRegion<BlockCodeRegion>(BD, locTy, AC, getCodeRegion()); 953 } 954 955 956 /// getSymbolicRegion - Retrieve or create a "symbolic" memory region. 957 const SymbolicRegion *MemRegionManager::getSymbolicRegion(SymbolRef sym) { 958 return getSubRegion<SymbolicRegion>(sym, getUnknownRegion()); 959 } 960 961 const SymbolicRegion *MemRegionManager::getSymbolicHeapRegion(SymbolRef Sym) { 962 return getSubRegion<SymbolicRegion>(Sym, getHeapRegion()); 963 } 964 965 const FieldRegion* 966 MemRegionManager::getFieldRegion(const FieldDecl *d, 967 const SubRegion* superRegion){ 968 return getSubRegion<FieldRegion>(d, superRegion); 969 } 970 971 const ObjCIvarRegion* 972 MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl *d, 973 const SubRegion* superRegion) { 974 return getSubRegion<ObjCIvarRegion>(d, superRegion); 975 } 976 977 const CXXTempObjectRegion* 978 MemRegionManager::getCXXTempObjectRegion(Expr const *E, 979 LocationContext const *LC) { 980 const StackFrameContext *SFC = LC->getCurrentStackFrame(); 981 assert(SFC); 982 return getSubRegion<CXXTempObjectRegion>(E, getStackLocalsRegion(SFC)); 983 } 984 985 /// Checks whether \p BaseClass is a valid virtual or direct non-virtual base 986 /// class of the type of \p Super. 987 static bool isValidBaseClass(const CXXRecordDecl *BaseClass, 988 const TypedValueRegion *Super, 989 bool IsVirtual) { 990 BaseClass = BaseClass->getCanonicalDecl(); 991 992 const CXXRecordDecl *Class = Super->getValueType()->getAsCXXRecordDecl(); 993 if (!Class) 994 return true; 995 996 if (IsVirtual) 997 return Class->isVirtuallyDerivedFrom(BaseClass); 998 999 for (const auto &I : Class->bases()) { 1000 if (I.getType()->getAsCXXRecordDecl()->getCanonicalDecl() == BaseClass) 1001 return true; 1002 } 1003 1004 return false; 1005 } 1006 1007 const CXXBaseObjectRegion * 1008 MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD, 1009 const SubRegion *Super, 1010 bool IsVirtual) { 1011 if (isa<TypedValueRegion>(Super)) { 1012 assert(isValidBaseClass(RD, dyn_cast<TypedValueRegion>(Super), IsVirtual)); 1013 (void)&isValidBaseClass; 1014 1015 if (IsVirtual) { 1016 // Virtual base regions should not be layered, since the layout rules 1017 // are different. 1018 while (const CXXBaseObjectRegion *Base = 1019 dyn_cast<CXXBaseObjectRegion>(Super)) { 1020 Super = cast<SubRegion>(Base->getSuperRegion()); 1021 } 1022 assert(Super && !isa<MemSpaceRegion>(Super)); 1023 } 1024 } 1025 1026 return getSubRegion<CXXBaseObjectRegion>(RD, IsVirtual, Super); 1027 } 1028 1029 const CXXThisRegion* 1030 MemRegionManager::getCXXThisRegion(QualType thisPointerTy, 1031 const LocationContext *LC) { 1032 const PointerType *PT = thisPointerTy->getAs<PointerType>(); 1033 assert(PT); 1034 // Inside the body of the operator() of a lambda a this expr might refer to an 1035 // object in one of the parent location contexts. 1036 const auto *D = dyn_cast<CXXMethodDecl>(LC->getDecl()); 1037 // FIXME: when operator() of lambda is analyzed as a top level function and 1038 // 'this' refers to a this to the enclosing scope, there is no right region to 1039 // return. 1040 while (!LC->inTopFrame() && 1041 (!D || D->isStatic() || 1042 PT != D->getThisType(getContext())->getAs<PointerType>())) { 1043 LC = LC->getParent(); 1044 D = dyn_cast<CXXMethodDecl>(LC->getDecl()); 1045 } 1046 const StackFrameContext *STC = LC->getCurrentStackFrame(); 1047 assert(STC); 1048 return getSubRegion<CXXThisRegion>(PT, getStackArgumentsRegion(STC)); 1049 } 1050 1051 const AllocaRegion* 1052 MemRegionManager::getAllocaRegion(const Expr *E, unsigned cnt, 1053 const LocationContext *LC) { 1054 const StackFrameContext *STC = LC->getCurrentStackFrame(); 1055 assert(STC); 1056 return getSubRegion<AllocaRegion>(E, cnt, getStackLocalsRegion(STC)); 1057 } 1058 1059 const MemSpaceRegion *MemRegion::getMemorySpace() const { 1060 const MemRegion *R = this; 1061 const SubRegion* SR = dyn_cast<SubRegion>(this); 1062 1063 while (SR) { 1064 R = SR->getSuperRegion(); 1065 SR = dyn_cast<SubRegion>(R); 1066 } 1067 1068 return dyn_cast<MemSpaceRegion>(R); 1069 } 1070 1071 bool MemRegion::hasStackStorage() const { 1072 return isa<StackSpaceRegion>(getMemorySpace()); 1073 } 1074 1075 bool MemRegion::hasStackNonParametersStorage() const { 1076 return isa<StackLocalsSpaceRegion>(getMemorySpace()); 1077 } 1078 1079 bool MemRegion::hasStackParametersStorage() const { 1080 return isa<StackArgumentsSpaceRegion>(getMemorySpace()); 1081 } 1082 1083 bool MemRegion::hasGlobalsOrParametersStorage() const { 1084 const MemSpaceRegion *MS = getMemorySpace(); 1085 return isa<StackArgumentsSpaceRegion>(MS) || 1086 isa<GlobalsSpaceRegion>(MS); 1087 } 1088 1089 // getBaseRegion strips away all elements and fields, and get the base region 1090 // of them. 1091 const MemRegion *MemRegion::getBaseRegion() const { 1092 const MemRegion *R = this; 1093 while (true) { 1094 switch (R->getKind()) { 1095 case MemRegion::ElementRegionKind: 1096 case MemRegion::FieldRegionKind: 1097 case MemRegion::ObjCIvarRegionKind: 1098 case MemRegion::CXXBaseObjectRegionKind: 1099 R = cast<SubRegion>(R)->getSuperRegion(); 1100 continue; 1101 default: 1102 break; 1103 } 1104 break; 1105 } 1106 return R; 1107 } 1108 1109 bool MemRegion::isSubRegionOf(const MemRegion *R) const { 1110 return false; 1111 } 1112 1113 //===----------------------------------------------------------------------===// 1114 // View handling. 1115 //===----------------------------------------------------------------------===// 1116 1117 const MemRegion *MemRegion::StripCasts(bool StripBaseCasts) const { 1118 const MemRegion *R = this; 1119 while (true) { 1120 switch (R->getKind()) { 1121 case ElementRegionKind: { 1122 const ElementRegion *ER = cast<ElementRegion>(R); 1123 if (!ER->getIndex().isZeroConstant()) 1124 return R; 1125 R = ER->getSuperRegion(); 1126 break; 1127 } 1128 case CXXBaseObjectRegionKind: 1129 if (!StripBaseCasts) 1130 return R; 1131 R = cast<CXXBaseObjectRegion>(R)->getSuperRegion(); 1132 break; 1133 default: 1134 return R; 1135 } 1136 } 1137 } 1138 1139 const SymbolicRegion *MemRegion::getSymbolicBase() const { 1140 const SubRegion *SubR = dyn_cast<SubRegion>(this); 1141 1142 while (SubR) { 1143 if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) 1144 return SymR; 1145 SubR = dyn_cast<SubRegion>(SubR->getSuperRegion()); 1146 } 1147 return nullptr; 1148 } 1149 1150 RegionRawOffset ElementRegion::getAsArrayOffset() const { 1151 CharUnits offset = CharUnits::Zero(); 1152 const ElementRegion *ER = this; 1153 const MemRegion *superR = nullptr; 1154 ASTContext &C = getContext(); 1155 1156 // FIXME: Handle multi-dimensional arrays. 1157 1158 while (ER) { 1159 superR = ER->getSuperRegion(); 1160 1161 // FIXME: generalize to symbolic offsets. 1162 SVal index = ER->getIndex(); 1163 if (Optional<nonloc::ConcreteInt> CI = index.getAs<nonloc::ConcreteInt>()) { 1164 // Update the offset. 1165 int64_t i = CI->getValue().getSExtValue(); 1166 1167 if (i != 0) { 1168 QualType elemType = ER->getElementType(); 1169 1170 // If we are pointing to an incomplete type, go no further. 1171 if (elemType->isIncompleteType()) { 1172 superR = ER; 1173 break; 1174 } 1175 1176 CharUnits size = C.getTypeSizeInChars(elemType); 1177 offset += (i * size); 1178 } 1179 1180 // Go to the next ElementRegion (if any). 1181 ER = dyn_cast<ElementRegion>(superR); 1182 continue; 1183 } 1184 1185 return nullptr; 1186 } 1187 1188 assert(superR && "super region cannot be NULL"); 1189 return RegionRawOffset(superR, offset); 1190 } 1191 1192 1193 /// Returns true if \p Base is an immediate base class of \p Child 1194 static bool isImmediateBase(const CXXRecordDecl *Child, 1195 const CXXRecordDecl *Base) { 1196 assert(Child && "Child must not be null"); 1197 // Note that we do NOT canonicalize the base class here, because 1198 // ASTRecordLayout doesn't either. If that leads us down the wrong path, 1199 // so be it; at least we won't crash. 1200 for (const auto &I : Child->bases()) { 1201 if (I.getType()->getAsCXXRecordDecl() == Base) 1202 return true; 1203 } 1204 1205 return false; 1206 } 1207 1208 RegionOffset MemRegion::getAsOffset() const { 1209 const MemRegion *R = this; 1210 const MemRegion *SymbolicOffsetBase = nullptr; 1211 int64_t Offset = 0; 1212 1213 while (1) { 1214 switch (R->getKind()) { 1215 case CodeSpaceRegionKind: 1216 case StackLocalsSpaceRegionKind: 1217 case StackArgumentsSpaceRegionKind: 1218 case HeapSpaceRegionKind: 1219 case UnknownSpaceRegionKind: 1220 case StaticGlobalSpaceRegionKind: 1221 case GlobalInternalSpaceRegionKind: 1222 case GlobalSystemSpaceRegionKind: 1223 case GlobalImmutableSpaceRegionKind: 1224 // Stores can bind directly to a region space to set a default value. 1225 assert(Offset == 0 && !SymbolicOffsetBase); 1226 goto Finish; 1227 1228 case FunctionCodeRegionKind: 1229 case BlockCodeRegionKind: 1230 case BlockDataRegionKind: 1231 // These will never have bindings, but may end up having values requested 1232 // if the user does some strange casting. 1233 if (Offset != 0) 1234 SymbolicOffsetBase = R; 1235 goto Finish; 1236 1237 case SymbolicRegionKind: 1238 case AllocaRegionKind: 1239 case CompoundLiteralRegionKind: 1240 case CXXThisRegionKind: 1241 case StringRegionKind: 1242 case ObjCStringRegionKind: 1243 case VarRegionKind: 1244 case CXXTempObjectRegionKind: 1245 // Usual base regions. 1246 goto Finish; 1247 1248 case ObjCIvarRegionKind: 1249 // This is a little strange, but it's a compromise between 1250 // ObjCIvarRegions having unknown compile-time offsets (when using the 1251 // non-fragile runtime) and yet still being distinct, non-overlapping 1252 // regions. Thus we treat them as "like" base regions for the purposes 1253 // of computing offsets. 1254 goto Finish; 1255 1256 case CXXBaseObjectRegionKind: { 1257 const CXXBaseObjectRegion *BOR = cast<CXXBaseObjectRegion>(R); 1258 R = BOR->getSuperRegion(); 1259 1260 QualType Ty; 1261 bool RootIsSymbolic = false; 1262 if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(R)) { 1263 Ty = TVR->getDesugaredValueType(getContext()); 1264 } else if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) { 1265 // If our base region is symbolic, we don't know what type it really is. 1266 // Pretend the type of the symbol is the true dynamic type. 1267 // (This will at least be self-consistent for the life of the symbol.) 1268 Ty = SR->getSymbol()->getType()->getPointeeType(); 1269 RootIsSymbolic = true; 1270 } 1271 1272 const CXXRecordDecl *Child = Ty->getAsCXXRecordDecl(); 1273 if (!Child) { 1274 // We cannot compute the offset of the base class. 1275 SymbolicOffsetBase = R; 1276 } else { 1277 if (RootIsSymbolic) { 1278 // Base layers on symbolic regions may not be type-correct. 1279 // Double-check the inheritance here, and revert to a symbolic offset 1280 // if it's invalid (e.g. due to a reinterpret_cast). 1281 if (BOR->isVirtual()) { 1282 if (!Child->isVirtuallyDerivedFrom(BOR->getDecl())) 1283 SymbolicOffsetBase = R; 1284 } else { 1285 if (!isImmediateBase(Child, BOR->getDecl())) 1286 SymbolicOffsetBase = R; 1287 } 1288 } 1289 } 1290 1291 // Don't bother calculating precise offsets if we already have a 1292 // symbolic offset somewhere in the chain. 1293 if (SymbolicOffsetBase) 1294 continue; 1295 1296 CharUnits BaseOffset; 1297 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Child); 1298 if (BOR->isVirtual()) 1299 BaseOffset = Layout.getVBaseClassOffset(BOR->getDecl()); 1300 else 1301 BaseOffset = Layout.getBaseClassOffset(BOR->getDecl()); 1302 1303 // The base offset is in chars, not in bits. 1304 Offset += BaseOffset.getQuantity() * getContext().getCharWidth(); 1305 break; 1306 } 1307 case ElementRegionKind: { 1308 const ElementRegion *ER = cast<ElementRegion>(R); 1309 R = ER->getSuperRegion(); 1310 1311 QualType EleTy = ER->getValueType(); 1312 if (EleTy->isIncompleteType()) { 1313 // We cannot compute the offset of the base class. 1314 SymbolicOffsetBase = R; 1315 continue; 1316 } 1317 1318 SVal Index = ER->getIndex(); 1319 if (Optional<nonloc::ConcreteInt> CI = 1320 Index.getAs<nonloc::ConcreteInt>()) { 1321 // Don't bother calculating precise offsets if we already have a 1322 // symbolic offset somewhere in the chain. 1323 if (SymbolicOffsetBase) 1324 continue; 1325 1326 int64_t i = CI->getValue().getSExtValue(); 1327 // This type size is in bits. 1328 Offset += i * getContext().getTypeSize(EleTy); 1329 } else { 1330 // We cannot compute offset for non-concrete index. 1331 SymbolicOffsetBase = R; 1332 } 1333 break; 1334 } 1335 case FieldRegionKind: { 1336 const FieldRegion *FR = cast<FieldRegion>(R); 1337 R = FR->getSuperRegion(); 1338 1339 const RecordDecl *RD = FR->getDecl()->getParent(); 1340 if (RD->isUnion() || !RD->isCompleteDefinition()) { 1341 // We cannot compute offset for incomplete type. 1342 // For unions, we could treat everything as offset 0, but we'd rather 1343 // treat each field as a symbolic offset so they aren't stored on top 1344 // of each other, since we depend on things in typed regions actually 1345 // matching their types. 1346 SymbolicOffsetBase = R; 1347 } 1348 1349 // Don't bother calculating precise offsets if we already have a 1350 // symbolic offset somewhere in the chain. 1351 if (SymbolicOffsetBase) 1352 continue; 1353 1354 // Get the field number. 1355 unsigned idx = 0; 1356 for (RecordDecl::field_iterator FI = RD->field_begin(), 1357 FE = RD->field_end(); FI != FE; ++FI, ++idx) { 1358 if (FR->getDecl() == *FI) 1359 break; 1360 } 1361 const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); 1362 // This is offset in bits. 1363 Offset += Layout.getFieldOffset(idx); 1364 break; 1365 } 1366 } 1367 } 1368 1369 Finish: 1370 if (SymbolicOffsetBase) 1371 return RegionOffset(SymbolicOffsetBase, RegionOffset::Symbolic); 1372 return RegionOffset(R, Offset); 1373 } 1374 1375 //===----------------------------------------------------------------------===// 1376 // BlockDataRegion 1377 //===----------------------------------------------------------------------===// 1378 1379 std::pair<const VarRegion *, const VarRegion *> 1380 BlockDataRegion::getCaptureRegions(const VarDecl *VD) { 1381 MemRegionManager &MemMgr = *getMemRegionManager(); 1382 const VarRegion *VR = nullptr; 1383 const VarRegion *OriginalVR = nullptr; 1384 1385 if (!VD->hasAttr<BlocksAttr>() && VD->hasLocalStorage()) { 1386 VR = MemMgr.getVarRegion(VD, this); 1387 OriginalVR = MemMgr.getVarRegion(VD, LC); 1388 } 1389 else { 1390 if (LC) { 1391 VR = MemMgr.getVarRegion(VD, LC); 1392 OriginalVR = VR; 1393 } 1394 else { 1395 VR = MemMgr.getVarRegion(VD, MemMgr.getUnknownRegion()); 1396 OriginalVR = MemMgr.getVarRegion(VD, LC); 1397 } 1398 } 1399 return std::make_pair(VR, OriginalVR); 1400 } 1401 1402 void BlockDataRegion::LazyInitializeReferencedVars() { 1403 if (ReferencedVars) 1404 return; 1405 1406 AnalysisDeclContext *AC = getCodeRegion()->getAnalysisDeclContext(); 1407 const auto &ReferencedBlockVars = AC->getReferencedBlockVars(BC->getDecl()); 1408 auto NumBlockVars = 1409 std::distance(ReferencedBlockVars.begin(), ReferencedBlockVars.end()); 1410 1411 if (NumBlockVars == 0) { 1412 ReferencedVars = (void*) 0x1; 1413 return; 1414 } 1415 1416 MemRegionManager &MemMgr = *getMemRegionManager(); 1417 llvm::BumpPtrAllocator &A = MemMgr.getAllocator(); 1418 BumpVectorContext BC(A); 1419 1420 typedef BumpVector<const MemRegion*> VarVec; 1421 VarVec *BV = A.Allocate<VarVec>(); 1422 new (BV) VarVec(BC, NumBlockVars); 1423 VarVec *BVOriginal = A.Allocate<VarVec>(); 1424 new (BVOriginal) VarVec(BC, NumBlockVars); 1425 1426 for (const VarDecl *VD : ReferencedBlockVars) { 1427 const VarRegion *VR = nullptr; 1428 const VarRegion *OriginalVR = nullptr; 1429 std::tie(VR, OriginalVR) = getCaptureRegions(VD); 1430 assert(VR); 1431 assert(OriginalVR); 1432 BV->push_back(VR, BC); 1433 BVOriginal->push_back(OriginalVR, BC); 1434 } 1435 1436 ReferencedVars = BV; 1437 OriginalVars = BVOriginal; 1438 } 1439 1440 BlockDataRegion::referenced_vars_iterator 1441 BlockDataRegion::referenced_vars_begin() const { 1442 const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars(); 1443 1444 BumpVector<const MemRegion*> *Vec = 1445 static_cast<BumpVector<const MemRegion*>*>(ReferencedVars); 1446 1447 if (Vec == (void*) 0x1) 1448 return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr); 1449 1450 BumpVector<const MemRegion*> *VecOriginal = 1451 static_cast<BumpVector<const MemRegion*>*>(OriginalVars); 1452 1453 return BlockDataRegion::referenced_vars_iterator(Vec->begin(), 1454 VecOriginal->begin()); 1455 } 1456 1457 BlockDataRegion::referenced_vars_iterator 1458 BlockDataRegion::referenced_vars_end() const { 1459 const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars(); 1460 1461 BumpVector<const MemRegion*> *Vec = 1462 static_cast<BumpVector<const MemRegion*>*>(ReferencedVars); 1463 1464 if (Vec == (void*) 0x1) 1465 return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr); 1466 1467 BumpVector<const MemRegion*> *VecOriginal = 1468 static_cast<BumpVector<const MemRegion*>*>(OriginalVars); 1469 1470 return BlockDataRegion::referenced_vars_iterator(Vec->end(), 1471 VecOriginal->end()); 1472 } 1473 1474 const VarRegion *BlockDataRegion::getOriginalRegion(const VarRegion *R) const { 1475 for (referenced_vars_iterator I = referenced_vars_begin(), 1476 E = referenced_vars_end(); 1477 I != E; ++I) { 1478 if (I.getCapturedRegion() == R) 1479 return I.getOriginalRegion(); 1480 } 1481 return nullptr; 1482 } 1483 1484 //===----------------------------------------------------------------------===// 1485 // RegionAndSymbolInvalidationTraits 1486 //===----------------------------------------------------------------------===// 1487 1488 void RegionAndSymbolInvalidationTraits::setTrait(SymbolRef Sym, 1489 InvalidationKinds IK) { 1490 SymTraitsMap[Sym] |= IK; 1491 } 1492 1493 void RegionAndSymbolInvalidationTraits::setTrait(const MemRegion *MR, 1494 InvalidationKinds IK) { 1495 assert(MR); 1496 if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR)) 1497 setTrait(SR->getSymbol(), IK); 1498 else 1499 MRTraitsMap[MR] |= IK; 1500 } 1501 1502 bool RegionAndSymbolInvalidationTraits::hasTrait(SymbolRef Sym, 1503 InvalidationKinds IK) const { 1504 const_symbol_iterator I = SymTraitsMap.find(Sym); 1505 if (I != SymTraitsMap.end()) 1506 return I->second & IK; 1507 1508 return false; 1509 } 1510 1511 bool RegionAndSymbolInvalidationTraits::hasTrait(const MemRegion *MR, 1512 InvalidationKinds IK) const { 1513 if (!MR) 1514 return false; 1515 1516 if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR)) 1517 return hasTrait(SR->getSymbol(), IK); 1518 1519 const_region_iterator I = MRTraitsMap.find(MR); 1520 if (I != MRTraitsMap.end()) 1521 return I->second & IK; 1522 1523 return false; 1524 } 1525