1 //===- MemRegion.cpp - Abstract memory regions for static analysis --------===// 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 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" 16 #include "clang/AST/ASTContext.h" 17 #include "clang/AST/Attr.h" 18 #include "clang/AST/CharUnits.h" 19 #include "clang/AST/Decl.h" 20 #include "clang/AST/DeclCXX.h" 21 #include "clang/AST/DeclObjC.h" 22 #include "clang/AST/Expr.h" 23 #include "clang/AST/PrettyPrinter.h" 24 #include "clang/AST/RecordLayout.h" 25 #include "clang/AST/Type.h" 26 #include "clang/Analysis/AnalysisDeclContext.h" 27 #include "clang/Analysis/Support/BumpVector.h" 28 #include "clang/Basic/IdentifierTable.h" 29 #include "clang/Basic/LLVM.h" 30 #include "clang/Basic/SourceManager.h" 31 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 32 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h" 33 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" 34 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 35 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" 36 #include "llvm/ADT/APInt.h" 37 #include "llvm/ADT/FoldingSet.h" 38 #include "llvm/ADT/PointerUnion.h" 39 #include "llvm/ADT/SmallString.h" 40 #include "llvm/ADT/StringRef.h" 41 #include "llvm/ADT/Twine.h" 42 #include "llvm/ADT/iterator_range.h" 43 #include "llvm/Support/Allocator.h" 44 #include "llvm/Support/Casting.h" 45 #include "llvm/Support/CheckedArithmetic.h" 46 #include "llvm/Support/Compiler.h" 47 #include "llvm/Support/Debug.h" 48 #include "llvm/Support/ErrorHandling.h" 49 #include "llvm/Support/raw_ostream.h" 50 #include <cassert> 51 #include <cstdint> 52 #include <functional> 53 #include <iterator> 54 #include <optional> 55 #include <string> 56 #include <tuple> 57 #include <utility> 58 59 using namespace clang; 60 using namespace ento; 61 62 #define DEBUG_TYPE "MemRegion" 63 64 //===----------------------------------------------------------------------===// 65 // MemRegion Construction. 66 //===----------------------------------------------------------------------===// 67 68 [[maybe_unused]] static bool isAReferenceTypedValueRegion(const MemRegion *R) { 69 const auto *TyReg = llvm::dyn_cast<TypedValueRegion>(R); 70 return TyReg && TyReg->getValueType()->isReferenceType(); 71 } 72 73 template <typename RegionTy, typename SuperTy, typename Arg1Ty> 74 RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, 75 const SuperTy *superRegion) { 76 llvm::FoldingSetNodeID ID; 77 RegionTy::ProfileRegion(ID, arg1, superRegion); 78 void *InsertPos; 79 auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos)); 80 81 if (!R) { 82 R = new (A) RegionTy(arg1, superRegion); 83 Regions.InsertNode(R, InsertPos); 84 assert(!isAReferenceTypedValueRegion(superRegion)); 85 } 86 87 return R; 88 } 89 90 template <typename RegionTy, typename SuperTy, typename Arg1Ty, typename Arg2Ty> 91 RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, 92 const SuperTy *superRegion) { 93 llvm::FoldingSetNodeID ID; 94 RegionTy::ProfileRegion(ID, arg1, arg2, superRegion); 95 void *InsertPos; 96 auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos)); 97 98 if (!R) { 99 R = new (A) RegionTy(arg1, arg2, superRegion); 100 Regions.InsertNode(R, InsertPos); 101 assert(!isAReferenceTypedValueRegion(superRegion)); 102 } 103 104 return R; 105 } 106 107 template <typename RegionTy, typename SuperTy, 108 typename Arg1Ty, typename Arg2Ty, typename Arg3Ty> 109 RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2, 110 const Arg3Ty arg3, 111 const SuperTy *superRegion) { 112 llvm::FoldingSetNodeID ID; 113 RegionTy::ProfileRegion(ID, arg1, arg2, arg3, superRegion); 114 void *InsertPos; 115 auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos)); 116 117 if (!R) { 118 R = new (A) RegionTy(arg1, arg2, arg3, superRegion); 119 Regions.InsertNode(R, InsertPos); 120 assert(!isAReferenceTypedValueRegion(superRegion)); 121 } 122 123 return R; 124 } 125 126 //===----------------------------------------------------------------------===// 127 // Object destruction. 128 //===----------------------------------------------------------------------===// 129 130 MemRegion::~MemRegion() = default; 131 132 // All regions and their data are BumpPtrAllocated. No need to call their 133 // destructors. 134 MemRegionManager::~MemRegionManager() = default; 135 136 //===----------------------------------------------------------------------===// 137 // Basic methods. 138 //===----------------------------------------------------------------------===// 139 140 bool SubRegion::isSubRegionOf(const MemRegion* R) const { 141 const MemRegion* r = this; 142 do { 143 if (r == R) 144 return true; 145 if (const auto *sr = dyn_cast<SubRegion>(r)) 146 r = sr->getSuperRegion(); 147 else 148 break; 149 } while (r != nullptr); 150 return false; 151 } 152 153 MemRegionManager &SubRegion::getMemRegionManager() const { 154 const SubRegion* r = this; 155 do { 156 const MemRegion *superRegion = r->getSuperRegion(); 157 if (const auto *sr = dyn_cast<SubRegion>(superRegion)) { 158 r = sr; 159 continue; 160 } 161 return superRegion->getMemRegionManager(); 162 } while (true); 163 } 164 165 const StackFrameContext *VarRegion::getStackFrame() const { 166 const auto *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace()); 167 return SSR ? SSR->getStackFrame() : nullptr; 168 } 169 170 const StackFrameContext * 171 CXXLifetimeExtendedObjectRegion::getStackFrame() const { 172 const auto *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace()); 173 return SSR ? SSR->getStackFrame() : nullptr; 174 } 175 176 const StackFrameContext *CXXTempObjectRegion::getStackFrame() const { 177 assert(isa<StackSpaceRegion>(getMemorySpace()) && 178 "A temporary object can only be allocated on the stack"); 179 return cast<StackSpaceRegion>(getMemorySpace())->getStackFrame(); 180 } 181 182 ObjCIvarRegion::ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg) 183 : DeclRegion(sReg, ObjCIvarRegionKind), IVD(ivd) { 184 assert(IVD); 185 } 186 187 const ObjCIvarDecl *ObjCIvarRegion::getDecl() const { return IVD; } 188 189 QualType ObjCIvarRegion::getValueType() const { 190 return getDecl()->getType(); 191 } 192 193 QualType CXXBaseObjectRegion::getValueType() const { 194 return QualType(getDecl()->getTypeForDecl(), 0); 195 } 196 197 QualType CXXDerivedObjectRegion::getValueType() const { 198 return QualType(getDecl()->getTypeForDecl(), 0); 199 } 200 201 QualType ParamVarRegion::getValueType() const { 202 assert(getDecl() && 203 "`ParamVarRegion` support functions without `Decl` not implemented" 204 " yet."); 205 return getDecl()->getType(); 206 } 207 208 const ParmVarDecl *ParamVarRegion::getDecl() const { 209 const Decl *D = getStackFrame()->getDecl(); 210 211 if (const auto *FD = dyn_cast<FunctionDecl>(D)) { 212 assert(Index < FD->param_size()); 213 return FD->parameters()[Index]; 214 } else if (const auto *BD = dyn_cast<BlockDecl>(D)) { 215 assert(Index < BD->param_size()); 216 return BD->parameters()[Index]; 217 } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) { 218 assert(Index < MD->param_size()); 219 return MD->parameters()[Index]; 220 } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) { 221 assert(Index < CD->param_size()); 222 return CD->parameters()[Index]; 223 } else { 224 llvm_unreachable("Unexpected Decl kind!"); 225 } 226 } 227 228 //===----------------------------------------------------------------------===// 229 // FoldingSet profiling. 230 //===----------------------------------------------------------------------===// 231 232 void MemSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const { 233 ID.AddInteger(static_cast<unsigned>(getKind())); 234 } 235 236 void StackSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const { 237 ID.AddInteger(static_cast<unsigned>(getKind())); 238 ID.AddPointer(getStackFrame()); 239 } 240 241 void StaticGlobalSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const { 242 ID.AddInteger(static_cast<unsigned>(getKind())); 243 ID.AddPointer(getCodeRegion()); 244 } 245 246 void StringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, 247 const StringLiteral *Str, 248 const MemRegion *superRegion) { 249 ID.AddInteger(static_cast<unsigned>(StringRegionKind)); 250 ID.AddPointer(Str); 251 ID.AddPointer(superRegion); 252 } 253 254 void ObjCStringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, 255 const ObjCStringLiteral *Str, 256 const MemRegion *superRegion) { 257 ID.AddInteger(static_cast<unsigned>(ObjCStringRegionKind)); 258 ID.AddPointer(Str); 259 ID.AddPointer(superRegion); 260 } 261 262 void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 263 const Expr *Ex, unsigned cnt, 264 const MemRegion *superRegion) { 265 ID.AddInteger(static_cast<unsigned>(AllocaRegionKind)); 266 ID.AddPointer(Ex); 267 ID.AddInteger(cnt); 268 ID.AddPointer(superRegion); 269 } 270 271 void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const { 272 ProfileRegion(ID, Ex, Cnt, superRegion); 273 } 274 275 void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const { 276 CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion); 277 } 278 279 void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 280 const CompoundLiteralExpr *CL, 281 const MemRegion* superRegion) { 282 ID.AddInteger(static_cast<unsigned>(CompoundLiteralRegionKind)); 283 ID.AddPointer(CL); 284 ID.AddPointer(superRegion); 285 } 286 287 void CXXThisRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, 288 const PointerType *PT, 289 const MemRegion *sRegion) { 290 ID.AddInteger(static_cast<unsigned>(CXXThisRegionKind)); 291 ID.AddPointer(PT); 292 ID.AddPointer(sRegion); 293 } 294 295 void CXXThisRegion::Profile(llvm::FoldingSetNodeID &ID) const { 296 CXXThisRegion::ProfileRegion(ID, ThisPointerTy, superRegion); 297 } 298 299 void FieldRegion::Profile(llvm::FoldingSetNodeID &ID) const { 300 ProfileRegion(ID, getDecl(), superRegion); 301 } 302 303 void ObjCIvarRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 304 const ObjCIvarDecl *ivd, 305 const MemRegion* superRegion) { 306 ID.AddInteger(static_cast<unsigned>(ObjCIvarRegionKind)); 307 ID.AddPointer(ivd); 308 ID.AddPointer(superRegion); 309 } 310 311 void ObjCIvarRegion::Profile(llvm::FoldingSetNodeID &ID) const { 312 ProfileRegion(ID, getDecl(), superRegion); 313 } 314 315 void NonParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, 316 const VarDecl *VD, 317 const MemRegion *superRegion) { 318 ID.AddInteger(static_cast<unsigned>(NonParamVarRegionKind)); 319 ID.AddPointer(VD); 320 ID.AddPointer(superRegion); 321 } 322 323 void NonParamVarRegion::Profile(llvm::FoldingSetNodeID &ID) const { 324 ProfileRegion(ID, getDecl(), superRegion); 325 } 326 327 void ParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, const Expr *OE, 328 unsigned Idx, const MemRegion *SReg) { 329 ID.AddInteger(static_cast<unsigned>(ParamVarRegionKind)); 330 ID.AddPointer(OE); 331 ID.AddInteger(Idx); 332 ID.AddPointer(SReg); 333 } 334 335 void ParamVarRegion::Profile(llvm::FoldingSetNodeID &ID) const { 336 ProfileRegion(ID, getOriginExpr(), getIndex(), superRegion); 337 } 338 339 void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym, 340 const MemRegion *sreg) { 341 ID.AddInteger(static_cast<unsigned>(MemRegion::SymbolicRegionKind)); 342 ID.Add(sym); 343 ID.AddPointer(sreg); 344 } 345 346 void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const { 347 SymbolicRegion::ProfileRegion(ID, sym, getSuperRegion()); 348 } 349 350 void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 351 QualType ElementType, SVal Idx, 352 const MemRegion* superRegion) { 353 ID.AddInteger(MemRegion::ElementRegionKind); 354 ID.Add(ElementType); 355 ID.AddPointer(superRegion); 356 Idx.Profile(ID); 357 } 358 359 void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const { 360 ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion); 361 } 362 363 void FunctionCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 364 const NamedDecl *FD, 365 const MemRegion*) { 366 ID.AddInteger(MemRegion::FunctionCodeRegionKind); 367 ID.AddPointer(FD); 368 } 369 370 void FunctionCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const { 371 FunctionCodeRegion::ProfileRegion(ID, FD, superRegion); 372 } 373 374 void BlockCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 375 const BlockDecl *BD, CanQualType, 376 const AnalysisDeclContext *AC, 377 const MemRegion*) { 378 ID.AddInteger(MemRegion::BlockCodeRegionKind); 379 ID.AddPointer(BD); 380 } 381 382 void BlockCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const { 383 BlockCodeRegion::ProfileRegion(ID, BD, locTy, AC, superRegion); 384 } 385 386 void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 387 const BlockCodeRegion *BC, 388 const LocationContext *LC, 389 unsigned BlkCount, 390 const MemRegion *sReg) { 391 ID.AddInteger(MemRegion::BlockDataRegionKind); 392 ID.AddPointer(BC); 393 ID.AddPointer(LC); 394 ID.AddInteger(BlkCount); 395 ID.AddPointer(sReg); 396 } 397 398 void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const { 399 BlockDataRegion::ProfileRegion(ID, BC, LC, BlockCount, getSuperRegion()); 400 } 401 402 void CXXTempObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, 403 Expr const *Ex, 404 const MemRegion *sReg) { 405 ID.AddPointer(Ex); 406 ID.AddPointer(sReg); 407 } 408 409 void CXXTempObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { 410 ProfileRegion(ID, Ex, getSuperRegion()); 411 } 412 413 void CXXLifetimeExtendedObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, 414 const Expr *E, 415 const ValueDecl *D, 416 const MemRegion *sReg) { 417 ID.AddPointer(E); 418 ID.AddPointer(D); 419 ID.AddPointer(sReg); 420 } 421 422 void CXXLifetimeExtendedObjectRegion::Profile( 423 llvm::FoldingSetNodeID &ID) const { 424 ProfileRegion(ID, Ex, ExD, getSuperRegion()); 425 } 426 427 void CXXBaseObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, 428 const CXXRecordDecl *RD, 429 bool IsVirtual, 430 const MemRegion *SReg) { 431 ID.AddPointer(RD); 432 ID.AddBoolean(IsVirtual); 433 ID.AddPointer(SReg); 434 } 435 436 void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { 437 ProfileRegion(ID, getDecl(), isVirtual(), superRegion); 438 } 439 440 void CXXDerivedObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, 441 const CXXRecordDecl *RD, 442 const MemRegion *SReg) { 443 ID.AddPointer(RD); 444 ID.AddPointer(SReg); 445 } 446 447 void CXXDerivedObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const { 448 ProfileRegion(ID, getDecl(), superRegion); 449 } 450 451 //===----------------------------------------------------------------------===// 452 // Region anchors. 453 //===----------------------------------------------------------------------===// 454 455 void GlobalsSpaceRegion::anchor() {} 456 457 void NonStaticGlobalSpaceRegion::anchor() {} 458 459 void StackSpaceRegion::anchor() {} 460 461 void TypedRegion::anchor() {} 462 463 void TypedValueRegion::anchor() {} 464 465 void CodeTextRegion::anchor() {} 466 467 void SubRegion::anchor() {} 468 469 //===----------------------------------------------------------------------===// 470 // Region pretty-printing. 471 //===----------------------------------------------------------------------===// 472 473 LLVM_DUMP_METHOD void MemRegion::dump() const { 474 dumpToStream(llvm::errs()); 475 } 476 477 std::string MemRegion::getString() const { 478 std::string s; 479 llvm::raw_string_ostream os(s); 480 dumpToStream(os); 481 return s; 482 } 483 484 void MemRegion::dumpToStream(raw_ostream &os) const { 485 os << "<Unknown Region>"; 486 } 487 488 void AllocaRegion::dumpToStream(raw_ostream &os) const { 489 os << "alloca{S" << Ex->getID(getContext()) << ',' << Cnt << '}'; 490 } 491 492 void FunctionCodeRegion::dumpToStream(raw_ostream &os) const { 493 os << "code{" << getDecl()->getDeclName().getAsString() << '}'; 494 } 495 496 void BlockCodeRegion::dumpToStream(raw_ostream &os) const { 497 os << "block_code{" << static_cast<const void *>(this) << '}'; 498 } 499 500 void BlockDataRegion::dumpToStream(raw_ostream &os) const { 501 os << "block_data{" << BC; 502 os << "; "; 503 for (auto Var : referenced_vars()) 504 os << "(" << Var.getCapturedRegion() << "<-" << Var.getOriginalRegion() 505 << ") "; 506 os << '}'; 507 } 508 509 void CompoundLiteralRegion::dumpToStream(raw_ostream &os) const { 510 // FIXME: More elaborate pretty-printing. 511 os << "{ S" << CL->getID(getContext()) << " }"; 512 } 513 514 void CXXTempObjectRegion::dumpToStream(raw_ostream &os) const { 515 os << "temp_object{" << getValueType() << ", " 516 << "S" << Ex->getID(getContext()) << '}'; 517 } 518 519 void CXXLifetimeExtendedObjectRegion::dumpToStream(raw_ostream &os) const { 520 os << "lifetime_extended_object{" << getValueType() << ", "; 521 if (const IdentifierInfo *ID = ExD->getIdentifier()) 522 os << ID->getName(); 523 else 524 os << "D" << ExD->getID(); 525 os << ", " 526 << "S" << Ex->getID(getContext()) << '}'; 527 } 528 529 void CXXBaseObjectRegion::dumpToStream(raw_ostream &os) const { 530 os << "Base{" << superRegion << ',' << getDecl()->getName() << '}'; 531 } 532 533 void CXXDerivedObjectRegion::dumpToStream(raw_ostream &os) const { 534 os << "Derived{" << superRegion << ',' << getDecl()->getName() << '}'; 535 } 536 537 void CXXThisRegion::dumpToStream(raw_ostream &os) const { 538 os << "this"; 539 } 540 541 void ElementRegion::dumpToStream(raw_ostream &os) const { 542 os << "Element{" << superRegion << ',' << Index << ',' << getElementType() 543 << '}'; 544 } 545 546 void FieldRegion::dumpToStream(raw_ostream &os) const { 547 os << superRegion << "." << *getDecl(); 548 } 549 550 void ObjCIvarRegion::dumpToStream(raw_ostream &os) const { 551 os << "Ivar{" << superRegion << ',' << *getDecl() << '}'; 552 } 553 554 void StringRegion::dumpToStream(raw_ostream &os) const { 555 assert(Str != nullptr && "Expecting non-null StringLiteral"); 556 Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts())); 557 } 558 559 void ObjCStringRegion::dumpToStream(raw_ostream &os) const { 560 assert(Str != nullptr && "Expecting non-null ObjCStringLiteral"); 561 Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts())); 562 } 563 564 void SymbolicRegion::dumpToStream(raw_ostream &os) const { 565 if (isa<HeapSpaceRegion>(getSuperRegion())) 566 os << "Heap"; 567 os << "SymRegion{" << sym << '}'; 568 } 569 570 void NonParamVarRegion::dumpToStream(raw_ostream &os) const { 571 if (const IdentifierInfo *ID = VD->getIdentifier()) 572 os << ID->getName(); 573 else 574 os << "NonParamVarRegion{D" << VD->getID() << '}'; 575 } 576 577 LLVM_DUMP_METHOD void RegionRawOffset::dump() const { 578 dumpToStream(llvm::errs()); 579 } 580 581 void RegionRawOffset::dumpToStream(raw_ostream &os) const { 582 os << "raw_offset{" << getRegion() << ',' << getOffset().getQuantity() << '}'; 583 } 584 585 void CodeSpaceRegion::dumpToStream(raw_ostream &os) const { 586 os << "CodeSpaceRegion"; 587 } 588 589 void StaticGlobalSpaceRegion::dumpToStream(raw_ostream &os) const { 590 os << "StaticGlobalsMemSpace{" << CR << '}'; 591 } 592 593 void GlobalInternalSpaceRegion::dumpToStream(raw_ostream &os) const { 594 os << "GlobalInternalSpaceRegion"; 595 } 596 597 void GlobalSystemSpaceRegion::dumpToStream(raw_ostream &os) const { 598 os << "GlobalSystemSpaceRegion"; 599 } 600 601 void GlobalImmutableSpaceRegion::dumpToStream(raw_ostream &os) const { 602 os << "GlobalImmutableSpaceRegion"; 603 } 604 605 void HeapSpaceRegion::dumpToStream(raw_ostream &os) const { 606 os << "HeapSpaceRegion"; 607 } 608 609 void UnknownSpaceRegion::dumpToStream(raw_ostream &os) const { 610 os << "UnknownSpaceRegion"; 611 } 612 613 void StackArgumentsSpaceRegion::dumpToStream(raw_ostream &os) const { 614 os << "StackArgumentsSpaceRegion"; 615 } 616 617 void StackLocalsSpaceRegion::dumpToStream(raw_ostream &os) const { 618 os << "StackLocalsSpaceRegion"; 619 } 620 621 void ParamVarRegion::dumpToStream(raw_ostream &os) const { 622 const ParmVarDecl *PVD = getDecl(); 623 assert(PVD && 624 "`ParamVarRegion` support functions without `Decl` not implemented" 625 " yet."); 626 if (const IdentifierInfo *ID = PVD->getIdentifier()) { 627 os << ID->getName(); 628 } else { 629 os << "ParamVarRegion{P" << PVD->getID() << '}'; 630 } 631 } 632 633 bool MemRegion::canPrintPretty() const { 634 return canPrintPrettyAsExpr(); 635 } 636 637 bool MemRegion::canPrintPrettyAsExpr() const { 638 return false; 639 } 640 641 StringRef MemRegion::getKindStr() const { 642 switch (getKind()) { 643 #define REGION(Id, Parent) \ 644 case Id##Kind: \ 645 return #Id; 646 #include "clang/StaticAnalyzer/Core/PathSensitive/Regions.def" 647 #undef REGION 648 } 649 llvm_unreachable("Unkown kind!"); 650 } 651 652 void MemRegion::printPretty(raw_ostream &os) const { 653 assert(canPrintPretty() && "This region cannot be printed pretty."); 654 os << "'"; 655 printPrettyAsExpr(os); 656 os << "'"; 657 } 658 659 void MemRegion::printPrettyAsExpr(raw_ostream &) const { 660 llvm_unreachable("This region cannot be printed pretty."); 661 } 662 663 bool NonParamVarRegion::canPrintPrettyAsExpr() const { return true; } 664 665 void NonParamVarRegion::printPrettyAsExpr(raw_ostream &os) const { 666 os << getDecl()->getName(); 667 } 668 669 bool ParamVarRegion::canPrintPrettyAsExpr() const { return true; } 670 671 void ParamVarRegion::printPrettyAsExpr(raw_ostream &os) const { 672 assert(getDecl() && 673 "`ParamVarRegion` support functions without `Decl` not implemented" 674 " yet."); 675 os << getDecl()->getName(); 676 } 677 678 bool ObjCIvarRegion::canPrintPrettyAsExpr() const { 679 return true; 680 } 681 682 void ObjCIvarRegion::printPrettyAsExpr(raw_ostream &os) const { 683 os << getDecl()->getName(); 684 } 685 686 bool FieldRegion::canPrintPretty() const { 687 return true; 688 } 689 690 bool FieldRegion::canPrintPrettyAsExpr() const { 691 return superRegion->canPrintPrettyAsExpr(); 692 } 693 694 void FieldRegion::printPrettyAsExpr(raw_ostream &os) const { 695 assert(canPrintPrettyAsExpr()); 696 superRegion->printPrettyAsExpr(os); 697 os << "." << getDecl()->getName(); 698 } 699 700 void FieldRegion::printPretty(raw_ostream &os) const { 701 if (canPrintPrettyAsExpr()) { 702 os << "\'"; 703 printPrettyAsExpr(os); 704 os << "'"; 705 } else { 706 os << "field " << "\'" << getDecl()->getName() << "'"; 707 } 708 } 709 710 bool CXXBaseObjectRegion::canPrintPrettyAsExpr() const { 711 return superRegion->canPrintPrettyAsExpr(); 712 } 713 714 void CXXBaseObjectRegion::printPrettyAsExpr(raw_ostream &os) const { 715 superRegion->printPrettyAsExpr(os); 716 } 717 718 bool CXXDerivedObjectRegion::canPrintPrettyAsExpr() const { 719 return superRegion->canPrintPrettyAsExpr(); 720 } 721 722 void CXXDerivedObjectRegion::printPrettyAsExpr(raw_ostream &os) const { 723 superRegion->printPrettyAsExpr(os); 724 } 725 726 std::string MemRegion::getDescriptiveName(bool UseQuotes) const { 727 std::string VariableName; 728 std::string ArrayIndices; 729 const MemRegion *R = this; 730 SmallString<50> buf; 731 llvm::raw_svector_ostream os(buf); 732 733 // Enclose subject with single quotes if needed. 734 auto QuoteIfNeeded = [UseQuotes](const Twine &Subject) -> std::string { 735 if (UseQuotes) 736 return ("'" + Subject + "'").str(); 737 return Subject.str(); 738 }; 739 740 // Obtain array indices to add them to the variable name. 741 const ElementRegion *ER = nullptr; 742 while ((ER = R->getAs<ElementRegion>())) { 743 // Index is a ConcreteInt. 744 if (auto CI = ER->getIndex().getAs<nonloc::ConcreteInt>()) { 745 llvm::SmallString<2> Idx; 746 CI->getValue()->toString(Idx); 747 ArrayIndices = (llvm::Twine("[") + Idx.str() + "]" + ArrayIndices).str(); 748 } 749 // Index is symbolic, but may have a descriptive name. 750 else { 751 auto SI = ER->getIndex().getAs<nonloc::SymbolVal>(); 752 if (!SI) 753 return ""; 754 755 const MemRegion *OR = SI->getAsSymbol()->getOriginRegion(); 756 if (!OR) 757 return ""; 758 759 std::string Idx = OR->getDescriptiveName(false); 760 if (Idx.empty()) 761 return ""; 762 763 ArrayIndices = (llvm::Twine("[") + Idx + "]" + ArrayIndices).str(); 764 } 765 R = ER->getSuperRegion(); 766 } 767 768 // Get variable name. 769 if (R) { 770 // MemRegion can be pretty printed. 771 if (R->canPrintPrettyAsExpr()) { 772 R->printPrettyAsExpr(os); 773 return QuoteIfNeeded(llvm::Twine(os.str()) + ArrayIndices); 774 } 775 776 // FieldRegion may have ElementRegion as SuperRegion. 777 if (const auto *FR = R->getAs<FieldRegion>()) { 778 std::string Super = FR->getSuperRegion()->getDescriptiveName(false); 779 if (Super.empty()) 780 return ""; 781 return QuoteIfNeeded(Super + "." + FR->getDecl()->getName()); 782 } 783 } 784 785 return VariableName; 786 } 787 788 SourceRange MemRegion::sourceRange() const { 789 // Check for more specific regions first. 790 if (auto *FR = dyn_cast<FieldRegion>(this)) { 791 return FR->getDecl()->getSourceRange(); 792 } 793 794 if (auto *VR = dyn_cast<VarRegion>(this->getBaseRegion())) { 795 return VR->getDecl()->getSourceRange(); 796 } 797 798 // Return invalid source range (can be checked by client). 799 return {}; 800 } 801 802 //===----------------------------------------------------------------------===// 803 // MemRegionManager methods. 804 //===----------------------------------------------------------------------===// 805 806 DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR, 807 SValBuilder &SVB) const { 808 const auto *SR = cast<SubRegion>(MR); 809 SymbolManager &SymMgr = SVB.getSymbolManager(); 810 811 switch (SR->getKind()) { 812 case MemRegion::AllocaRegionKind: 813 case MemRegion::SymbolicRegionKind: 814 return nonloc::SymbolVal(SymMgr.acquire<SymbolExtent>(SR)); 815 case MemRegion::StringRegionKind: 816 return SVB.makeIntVal( 817 cast<StringRegion>(SR)->getStringLiteral()->getByteLength() + 1, 818 SVB.getArrayIndexType()); 819 case MemRegion::CompoundLiteralRegionKind: 820 case MemRegion::CXXBaseObjectRegionKind: 821 case MemRegion::CXXDerivedObjectRegionKind: 822 case MemRegion::CXXTempObjectRegionKind: 823 case MemRegion::CXXLifetimeExtendedObjectRegionKind: 824 case MemRegion::CXXThisRegionKind: 825 case MemRegion::ObjCIvarRegionKind: 826 case MemRegion::NonParamVarRegionKind: 827 case MemRegion::ParamVarRegionKind: 828 case MemRegion::ElementRegionKind: 829 case MemRegion::ObjCStringRegionKind: { 830 QualType Ty = cast<TypedValueRegion>(SR)->getDesugaredValueType(Ctx); 831 if (isa<VariableArrayType>(Ty)) 832 return nonloc::SymbolVal(SymMgr.acquire<SymbolExtent>(SR)); 833 834 if (Ty->isIncompleteType()) 835 return UnknownVal(); 836 837 return getElementExtent(Ty, SVB); 838 } 839 case MemRegion::FieldRegionKind: { 840 // Force callers to deal with bitfields explicitly. 841 if (cast<FieldRegion>(SR)->getDecl()->isBitField()) 842 return UnknownVal(); 843 844 QualType Ty = cast<TypedValueRegion>(SR)->getDesugaredValueType(Ctx); 845 const DefinedOrUnknownSVal Size = getElementExtent(Ty, SVB); 846 847 // We currently don't model flexible array members (FAMs), which are: 848 // - int array[]; of IncompleteArrayType 849 // - int array[0]; of ConstantArrayType with size 0 850 // - int array[1]; of ConstantArrayType with size 1 851 // https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html 852 const auto isFlexibleArrayMemberCandidate = 853 [this](const ArrayType *AT) -> bool { 854 if (!AT) 855 return false; 856 857 auto IsIncompleteArray = [](const ArrayType *AT) { 858 return isa<IncompleteArrayType>(AT); 859 }; 860 auto IsArrayOfZero = [](const ArrayType *AT) { 861 const auto *CAT = dyn_cast<ConstantArrayType>(AT); 862 return CAT && CAT->isZeroSize(); 863 }; 864 auto IsArrayOfOne = [](const ArrayType *AT) { 865 const auto *CAT = dyn_cast<ConstantArrayType>(AT); 866 return CAT && CAT->getSize() == 1; 867 }; 868 869 using FAMKind = LangOptions::StrictFlexArraysLevelKind; 870 const FAMKind StrictFlexArraysLevel = 871 Ctx.getLangOpts().getStrictFlexArraysLevel(); 872 873 // "Default": Any trailing array member is a FAM. 874 // Since we cannot tell at this point if this array is a trailing member 875 // or not, let's just do the same as for "OneZeroOrIncomplete". 876 if (StrictFlexArraysLevel == FAMKind::Default) 877 return IsArrayOfOne(AT) || IsArrayOfZero(AT) || IsIncompleteArray(AT); 878 879 if (StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete) 880 return IsArrayOfOne(AT) || IsArrayOfZero(AT) || IsIncompleteArray(AT); 881 882 if (StrictFlexArraysLevel == FAMKind::ZeroOrIncomplete) 883 return IsArrayOfZero(AT) || IsIncompleteArray(AT); 884 885 assert(StrictFlexArraysLevel == FAMKind::IncompleteOnly); 886 return IsIncompleteArray(AT); 887 }; 888 889 if (isFlexibleArrayMemberCandidate(Ctx.getAsArrayType(Ty))) 890 return UnknownVal(); 891 892 return Size; 893 } 894 // FIXME: The following are being used in 'SimpleSValBuilder' and in 895 // 'ArrayBoundChecker::checkLocation' because there is no symbol to 896 // represent the regions more appropriately. 897 case MemRegion::BlockDataRegionKind: 898 case MemRegion::BlockCodeRegionKind: 899 case MemRegion::FunctionCodeRegionKind: 900 return nonloc::SymbolVal(SymMgr.acquire<SymbolExtent>(SR)); 901 default: 902 llvm_unreachable("Unhandled region"); 903 } 904 } 905 906 template <typename REG> 907 const REG *MemRegionManager::LazyAllocate(REG*& region) { 908 if (!region) { 909 region = new (A) REG(*this); 910 } 911 912 return region; 913 } 914 915 template <typename REG, typename ARG> 916 const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) { 917 if (!region) { 918 region = new (A) REG(this, a); 919 } 920 921 return region; 922 } 923 924 const StackLocalsSpaceRegion* 925 MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) { 926 assert(STC); 927 StackLocalsSpaceRegion *&R = StackLocalsSpaceRegions[STC]; 928 929 if (R) 930 return R; 931 932 R = new (A) StackLocalsSpaceRegion(*this, STC); 933 return R; 934 } 935 936 const StackArgumentsSpaceRegion * 937 MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) { 938 assert(STC); 939 StackArgumentsSpaceRegion *&R = StackArgumentsSpaceRegions[STC]; 940 941 if (R) 942 return R; 943 944 R = new (A) StackArgumentsSpaceRegion(*this, STC); 945 return R; 946 } 947 948 const GlobalsSpaceRegion 949 *MemRegionManager::getGlobalsRegion(MemRegion::Kind K, 950 const CodeTextRegion *CR) { 951 if (!CR) { 952 if (K == MemRegion::GlobalSystemSpaceRegionKind) 953 return LazyAllocate(SystemGlobals); 954 if (K == MemRegion::GlobalImmutableSpaceRegionKind) 955 return LazyAllocate(ImmutableGlobals); 956 assert(K == MemRegion::GlobalInternalSpaceRegionKind); 957 return LazyAllocate(InternalGlobals); 958 } 959 960 assert(K == MemRegion::StaticGlobalSpaceRegionKind); 961 StaticGlobalSpaceRegion *&R = StaticsGlobalSpaceRegions[CR]; 962 if (R) 963 return R; 964 965 R = new (A) StaticGlobalSpaceRegion(*this, CR); 966 return R; 967 } 968 969 const HeapSpaceRegion *MemRegionManager::getHeapRegion() { 970 return LazyAllocate(heap); 971 } 972 973 const UnknownSpaceRegion *MemRegionManager::getUnknownRegion() { 974 return LazyAllocate(unknown); 975 } 976 977 const CodeSpaceRegion *MemRegionManager::getCodeRegion() { 978 return LazyAllocate(code); 979 } 980 981 //===----------------------------------------------------------------------===// 982 // Constructing regions. 983 //===----------------------------------------------------------------------===// 984 985 const StringRegion *MemRegionManager::getStringRegion(const StringLiteral *Str){ 986 return getSubRegion<StringRegion>( 987 Str, cast<GlobalInternalSpaceRegion>(getGlobalsRegion())); 988 } 989 990 const ObjCStringRegion * 991 MemRegionManager::getObjCStringRegion(const ObjCStringLiteral *Str){ 992 return getSubRegion<ObjCStringRegion>( 993 Str, cast<GlobalInternalSpaceRegion>(getGlobalsRegion())); 994 } 995 996 /// Look through a chain of LocationContexts to either find the 997 /// StackFrameContext that matches a DeclContext, or find a VarRegion 998 /// for a variable captured by a block. 999 static llvm::PointerUnion<const StackFrameContext *, const VarRegion *> 1000 getStackOrCaptureRegionForDeclContext(const LocationContext *LC, 1001 const DeclContext *DC, 1002 const VarDecl *VD) { 1003 while (LC) { 1004 if (const auto *SFC = dyn_cast<StackFrameContext>(LC)) { 1005 if (cast<DeclContext>(SFC->getDecl()) == DC) 1006 return SFC; 1007 } 1008 if (const auto *BC = dyn_cast<BlockInvocationContext>(LC)) { 1009 const auto *BR = static_cast<const BlockDataRegion *>(BC->getData()); 1010 // FIXME: This can be made more efficient. 1011 for (auto Var : BR->referenced_vars()) { 1012 const TypedValueRegion *OrigR = Var.getOriginalRegion(); 1013 if (const auto *VR = dyn_cast<VarRegion>(OrigR)) { 1014 if (VR->getDecl() == VD) 1015 return cast<VarRegion>(Var.getCapturedRegion()); 1016 } 1017 } 1018 } 1019 1020 LC = LC->getParent(); 1021 } 1022 return (const StackFrameContext *)nullptr; 1023 } 1024 1025 const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D, 1026 const LocationContext *LC) { 1027 const auto *PVD = dyn_cast<ParmVarDecl>(D); 1028 if (PVD) { 1029 unsigned Index = PVD->getFunctionScopeIndex(); 1030 const StackFrameContext *SFC = LC->getStackFrame(); 1031 const Stmt *CallSite = SFC->getCallSite(); 1032 if (CallSite) { 1033 const Decl *D = SFC->getDecl(); 1034 if (const auto *FD = dyn_cast<FunctionDecl>(D)) { 1035 if (Index < FD->param_size() && FD->parameters()[Index] == PVD) 1036 return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index, 1037 getStackArgumentsRegion(SFC)); 1038 } else if (const auto *BD = dyn_cast<BlockDecl>(D)) { 1039 if (Index < BD->param_size() && BD->parameters()[Index] == PVD) 1040 return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index, 1041 getStackArgumentsRegion(SFC)); 1042 } else { 1043 return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index, 1044 getStackArgumentsRegion(SFC)); 1045 } 1046 } 1047 } 1048 1049 D = D->getCanonicalDecl(); 1050 const MemRegion *sReg = nullptr; 1051 1052 if (D->hasGlobalStorage() && !D->isStaticLocal()) { 1053 QualType Ty = D->getType(); 1054 assert(!Ty.isNull()); 1055 if (Ty.isConstQualified()) { 1056 sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); 1057 } else if (Ctx.getSourceManager().isInSystemHeader(D->getLocation())) { 1058 sReg = getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind); 1059 } else { 1060 sReg = getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind); 1061 } 1062 1063 // Finally handle static locals. 1064 } else { 1065 // FIXME: Once we implement scope handling, we will need to properly lookup 1066 // 'D' to the proper LocationContext. 1067 const DeclContext *DC = D->getDeclContext(); 1068 llvm::PointerUnion<const StackFrameContext *, const VarRegion *> V = 1069 getStackOrCaptureRegionForDeclContext(LC, DC, D); 1070 1071 if (const auto *VR = dyn_cast_if_present<const VarRegion *>(V)) 1072 return VR; 1073 1074 const auto *STC = cast<const StackFrameContext *>(V); 1075 1076 if (!STC) { 1077 // FIXME: Assign a more sensible memory space to static locals 1078 // we see from within blocks that we analyze as top-level declarations. 1079 sReg = getUnknownRegion(); 1080 } else { 1081 if (D->hasLocalStorage()) { 1082 sReg = 1083 isa<ParmVarDecl, ImplicitParamDecl>(D) 1084 ? static_cast<const MemRegion *>(getStackArgumentsRegion(STC)) 1085 : static_cast<const MemRegion *>(getStackLocalsRegion(STC)); 1086 } 1087 else { 1088 assert(D->isStaticLocal()); 1089 const Decl *STCD = STC->getDecl(); 1090 if (isa<FunctionDecl, ObjCMethodDecl>(STCD)) 1091 sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, 1092 getFunctionCodeRegion(cast<NamedDecl>(STCD))); 1093 else if (const auto *BD = dyn_cast<BlockDecl>(STCD)) { 1094 // FIXME: The fallback type here is totally bogus -- though it should 1095 // never be queried, it will prevent uniquing with the real 1096 // BlockCodeRegion. Ideally we'd fix the AST so that we always had a 1097 // signature. 1098 QualType T; 1099 if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten()) 1100 T = TSI->getType(); 1101 if (T.isNull()) 1102 T = getContext().VoidTy; 1103 if (!T->getAs<FunctionType>()) { 1104 FunctionProtoType::ExtProtoInfo Ext; 1105 T = getContext().getFunctionType(T, {}, Ext); 1106 } 1107 T = getContext().getBlockPointerType(T); 1108 1109 const BlockCodeRegion *BTR = 1110 getBlockCodeRegion(BD, Ctx.getCanonicalType(T), 1111 STC->getAnalysisDeclContext()); 1112 sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, 1113 BTR); 1114 } 1115 else { 1116 sReg = getGlobalsRegion(); 1117 } 1118 } 1119 } 1120 } 1121 1122 return getNonParamVarRegion(D, sReg); 1123 } 1124 1125 const NonParamVarRegion * 1126 MemRegionManager::getNonParamVarRegion(const VarDecl *D, 1127 const MemRegion *superR) { 1128 // Prefer the definition over the canonical decl as the canonical form. 1129 D = D->getCanonicalDecl(); 1130 if (const VarDecl *Def = D->getDefinition()) 1131 D = Def; 1132 return getSubRegion<NonParamVarRegion>(D, superR); 1133 } 1134 1135 const ParamVarRegion * 1136 MemRegionManager::getParamVarRegion(const Expr *OriginExpr, unsigned Index, 1137 const LocationContext *LC) { 1138 const StackFrameContext *SFC = LC->getStackFrame(); 1139 assert(SFC); 1140 return getSubRegion<ParamVarRegion>(OriginExpr, Index, 1141 getStackArgumentsRegion(SFC)); 1142 } 1143 1144 const BlockDataRegion * 1145 MemRegionManager::getBlockDataRegion(const BlockCodeRegion *BC, 1146 const LocationContext *LC, 1147 unsigned blockCount) { 1148 const MemSpaceRegion *sReg = nullptr; 1149 const BlockDecl *BD = BC->getDecl(); 1150 if (!BD->hasCaptures()) { 1151 // This handles 'static' blocks. 1152 sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind); 1153 } 1154 else { 1155 bool IsArcManagedBlock = Ctx.getLangOpts().ObjCAutoRefCount; 1156 1157 // ARC managed blocks can be initialized on stack or directly in heap 1158 // depending on the implementations. So we initialize them with 1159 // UnknownRegion. 1160 if (!IsArcManagedBlock && LC) { 1161 // FIXME: Once we implement scope handling, we want the parent region 1162 // to be the scope. 1163 const StackFrameContext *STC = LC->getStackFrame(); 1164 assert(STC); 1165 sReg = getStackLocalsRegion(STC); 1166 } else { 1167 // We allow 'LC' to be NULL for cases where want BlockDataRegions 1168 // without context-sensitivity. 1169 sReg = getUnknownRegion(); 1170 } 1171 } 1172 1173 return getSubRegion<BlockDataRegion>(BC, LC, blockCount, sReg); 1174 } 1175 1176 const CompoundLiteralRegion* 1177 MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL, 1178 const LocationContext *LC) { 1179 const MemSpaceRegion *sReg = nullptr; 1180 1181 if (CL->isFileScope()) 1182 sReg = getGlobalsRegion(); 1183 else { 1184 const StackFrameContext *STC = LC->getStackFrame(); 1185 assert(STC); 1186 sReg = getStackLocalsRegion(STC); 1187 } 1188 1189 return getSubRegion<CompoundLiteralRegion>(CL, sReg); 1190 } 1191 1192 const ElementRegion * 1193 MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx, 1194 const SubRegion *superRegion, 1195 const ASTContext &Ctx) { 1196 QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType(); 1197 1198 llvm::FoldingSetNodeID ID; 1199 ElementRegion::ProfileRegion(ID, T, Idx, superRegion); 1200 1201 void *InsertPos; 1202 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); 1203 auto *R = cast_or_null<ElementRegion>(data); 1204 1205 if (!R) { 1206 R = new (A) ElementRegion(T, Idx, superRegion); 1207 Regions.InsertNode(R, InsertPos); 1208 } 1209 1210 return R; 1211 } 1212 1213 const FunctionCodeRegion * 1214 MemRegionManager::getFunctionCodeRegion(const NamedDecl *FD) { 1215 // To think: should we canonicalize the declaration here? 1216 return getSubRegion<FunctionCodeRegion>(FD, getCodeRegion()); 1217 } 1218 1219 const BlockCodeRegion * 1220 MemRegionManager::getBlockCodeRegion(const BlockDecl *BD, CanQualType locTy, 1221 AnalysisDeclContext *AC) { 1222 return getSubRegion<BlockCodeRegion>(BD, locTy, AC, getCodeRegion()); 1223 } 1224 1225 const SymbolicRegion * 1226 MemRegionManager::getSymbolicRegion(SymbolRef sym, 1227 const MemSpaceRegion *MemSpace) { 1228 if (MemSpace == nullptr) 1229 MemSpace = getUnknownRegion(); 1230 return getSubRegion<SymbolicRegion>(sym, MemSpace); 1231 } 1232 1233 const SymbolicRegion *MemRegionManager::getSymbolicHeapRegion(SymbolRef Sym) { 1234 return getSubRegion<SymbolicRegion>(Sym, getHeapRegion()); 1235 } 1236 1237 const FieldRegion* 1238 MemRegionManager::getFieldRegion(const FieldDecl *d, 1239 const SubRegion* superRegion){ 1240 return getSubRegion<FieldRegion>(d, superRegion); 1241 } 1242 1243 const ObjCIvarRegion* 1244 MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl *d, 1245 const SubRegion* superRegion) { 1246 return getSubRegion<ObjCIvarRegion>(d, superRegion); 1247 } 1248 1249 const CXXTempObjectRegion* 1250 MemRegionManager::getCXXTempObjectRegion(Expr const *E, 1251 LocationContext const *LC) { 1252 const StackFrameContext *SFC = LC->getStackFrame(); 1253 assert(SFC); 1254 return getSubRegion<CXXTempObjectRegion>(E, getStackLocalsRegion(SFC)); 1255 } 1256 1257 const CXXLifetimeExtendedObjectRegion * 1258 MemRegionManager::getCXXLifetimeExtendedObjectRegion( 1259 const Expr *Ex, const ValueDecl *VD, const LocationContext *LC) { 1260 const StackFrameContext *SFC = LC->getStackFrame(); 1261 assert(SFC); 1262 return getSubRegion<CXXLifetimeExtendedObjectRegion>( 1263 Ex, VD, getStackLocalsRegion(SFC)); 1264 } 1265 1266 const CXXLifetimeExtendedObjectRegion * 1267 MemRegionManager::getCXXStaticLifetimeExtendedObjectRegion( 1268 const Expr *Ex, const ValueDecl *VD) { 1269 return getSubRegion<CXXLifetimeExtendedObjectRegion>( 1270 Ex, VD, 1271 getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind, nullptr)); 1272 } 1273 1274 /// Checks whether \p BaseClass is a valid virtual or direct non-virtual base 1275 /// class of the type of \p Super. 1276 static bool isValidBaseClass(const CXXRecordDecl *BaseClass, 1277 const TypedValueRegion *Super, 1278 bool IsVirtual) { 1279 BaseClass = BaseClass->getCanonicalDecl(); 1280 1281 const CXXRecordDecl *Class = Super->getValueType()->getAsCXXRecordDecl(); 1282 if (!Class) 1283 return true; 1284 1285 if (IsVirtual) 1286 return Class->isVirtuallyDerivedFrom(BaseClass); 1287 1288 for (const auto &I : Class->bases()) { 1289 if (I.getType()->getAsCXXRecordDecl()->getCanonicalDecl() == BaseClass) 1290 return true; 1291 } 1292 1293 return false; 1294 } 1295 1296 const CXXBaseObjectRegion * 1297 MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD, 1298 const SubRegion *Super, 1299 bool IsVirtual) { 1300 if (isa<TypedValueRegion>(Super)) { 1301 assert(isValidBaseClass(RD, cast<TypedValueRegion>(Super), IsVirtual)); 1302 (void)&isValidBaseClass; 1303 1304 if (IsVirtual) { 1305 // Virtual base regions should not be layered, since the layout rules 1306 // are different. 1307 while (const auto *Base = dyn_cast<CXXBaseObjectRegion>(Super)) 1308 Super = cast<SubRegion>(Base->getSuperRegion()); 1309 assert(Super && !isa<MemSpaceRegion>(Super)); 1310 } 1311 } 1312 1313 return getSubRegion<CXXBaseObjectRegion>(RD, IsVirtual, Super); 1314 } 1315 1316 const CXXDerivedObjectRegion * 1317 MemRegionManager::getCXXDerivedObjectRegion(const CXXRecordDecl *RD, 1318 const SubRegion *Super) { 1319 return getSubRegion<CXXDerivedObjectRegion>(RD, Super); 1320 } 1321 1322 const CXXThisRegion* 1323 MemRegionManager::getCXXThisRegion(QualType thisPointerTy, 1324 const LocationContext *LC) { 1325 const auto *PT = thisPointerTy->getAs<PointerType>(); 1326 assert(PT); 1327 // Inside the body of the operator() of a lambda a this expr might refer to an 1328 // object in one of the parent location contexts. 1329 const auto *D = dyn_cast<CXXMethodDecl>(LC->getDecl()); 1330 // FIXME: when operator() of lambda is analyzed as a top level function and 1331 // 'this' refers to a this to the enclosing scope, there is no right region to 1332 // return. 1333 while (!LC->inTopFrame() && (!D || D->isStatic() || 1334 PT != D->getThisType()->getAs<PointerType>())) { 1335 LC = LC->getParent(); 1336 D = dyn_cast<CXXMethodDecl>(LC->getDecl()); 1337 } 1338 const StackFrameContext *STC = LC->getStackFrame(); 1339 assert(STC); 1340 return getSubRegion<CXXThisRegion>(PT, getStackArgumentsRegion(STC)); 1341 } 1342 1343 const AllocaRegion* 1344 MemRegionManager::getAllocaRegion(const Expr *E, unsigned cnt, 1345 const LocationContext *LC) { 1346 const StackFrameContext *STC = LC->getStackFrame(); 1347 assert(STC); 1348 return getSubRegion<AllocaRegion>(E, cnt, getStackLocalsRegion(STC)); 1349 } 1350 1351 const MemSpaceRegion *MemRegion::getMemorySpace() const { 1352 const MemRegion *R = this; 1353 const auto *SR = dyn_cast<SubRegion>(this); 1354 1355 while (SR) { 1356 R = SR->getSuperRegion(); 1357 SR = dyn_cast<SubRegion>(R); 1358 } 1359 1360 return cast<MemSpaceRegion>(R); 1361 } 1362 1363 bool MemRegion::hasStackStorage() const { 1364 return isa<StackSpaceRegion>(getMemorySpace()); 1365 } 1366 1367 bool MemRegion::hasStackNonParametersStorage() const { 1368 return isa<StackLocalsSpaceRegion>(getMemorySpace()); 1369 } 1370 1371 bool MemRegion::hasStackParametersStorage() const { 1372 return isa<StackArgumentsSpaceRegion>(getMemorySpace()); 1373 } 1374 1375 // Strips away all elements and fields. 1376 // Returns the base region of them. 1377 const MemRegion *MemRegion::getBaseRegion() const { 1378 const MemRegion *R = this; 1379 while (true) { 1380 switch (R->getKind()) { 1381 case MemRegion::ElementRegionKind: 1382 case MemRegion::FieldRegionKind: 1383 case MemRegion::ObjCIvarRegionKind: 1384 case MemRegion::CXXBaseObjectRegionKind: 1385 case MemRegion::CXXDerivedObjectRegionKind: 1386 R = cast<SubRegion>(R)->getSuperRegion(); 1387 continue; 1388 default: 1389 break; 1390 } 1391 break; 1392 } 1393 return R; 1394 } 1395 1396 // Returns the region of the root class of a C++ class hierarchy. 1397 const MemRegion *MemRegion::getMostDerivedObjectRegion() const { 1398 const MemRegion *R = this; 1399 while (const auto *BR = dyn_cast<CXXBaseObjectRegion>(R)) 1400 R = BR->getSuperRegion(); 1401 return R; 1402 } 1403 1404 bool MemRegion::isSubRegionOf(const MemRegion *) const { 1405 return false; 1406 } 1407 1408 //===----------------------------------------------------------------------===// 1409 // View handling. 1410 //===----------------------------------------------------------------------===// 1411 1412 const MemRegion *MemRegion::StripCasts(bool StripBaseAndDerivedCasts) const { 1413 const MemRegion *R = this; 1414 while (true) { 1415 switch (R->getKind()) { 1416 case ElementRegionKind: { 1417 const auto *ER = cast<ElementRegion>(R); 1418 if (!ER->getIndex().isZeroConstant()) 1419 return R; 1420 R = ER->getSuperRegion(); 1421 break; 1422 } 1423 case CXXBaseObjectRegionKind: 1424 case CXXDerivedObjectRegionKind: 1425 if (!StripBaseAndDerivedCasts) 1426 return R; 1427 R = cast<TypedValueRegion>(R)->getSuperRegion(); 1428 break; 1429 default: 1430 return R; 1431 } 1432 } 1433 } 1434 1435 const SymbolicRegion *MemRegion::getSymbolicBase() const { 1436 const auto *SubR = dyn_cast<SubRegion>(this); 1437 1438 while (SubR) { 1439 if (const auto *SymR = dyn_cast<SymbolicRegion>(SubR)) 1440 return SymR; 1441 SubR = dyn_cast<SubRegion>(SubR->getSuperRegion()); 1442 } 1443 return nullptr; 1444 } 1445 1446 RegionRawOffset ElementRegion::getAsArrayOffset() const { 1447 int64_t offset = 0; 1448 const ElementRegion *ER = this; 1449 const MemRegion *superR = nullptr; 1450 ASTContext &C = getContext(); 1451 1452 // FIXME: Handle multi-dimensional arrays. 1453 1454 while (ER) { 1455 superR = ER->getSuperRegion(); 1456 1457 // FIXME: generalize to symbolic offsets. 1458 SVal index = ER->getIndex(); 1459 if (auto CI = index.getAs<nonloc::ConcreteInt>()) { 1460 // Update the offset. 1461 if (int64_t i = CI->getValue()->getSExtValue(); i != 0) { 1462 QualType elemType = ER->getElementType(); 1463 1464 // If we are pointing to an incomplete type, go no further. 1465 if (elemType->isIncompleteType()) { 1466 superR = ER; 1467 break; 1468 } 1469 1470 int64_t size = C.getTypeSizeInChars(elemType).getQuantity(); 1471 if (auto NewOffset = llvm::checkedMulAdd(i, size, offset)) { 1472 offset = *NewOffset; 1473 } else { 1474 LLVM_DEBUG(llvm::dbgs() << "MemRegion::getAsArrayOffset: " 1475 << "offset overflowing, returning unknown\n"); 1476 1477 return nullptr; 1478 } 1479 } 1480 1481 // Go to the next ElementRegion (if any). 1482 ER = dyn_cast<ElementRegion>(superR); 1483 continue; 1484 } 1485 1486 return nullptr; 1487 } 1488 1489 assert(superR && "super region cannot be NULL"); 1490 return RegionRawOffset(superR, CharUnits::fromQuantity(offset)); 1491 } 1492 1493 /// Returns true if \p Base is an immediate base class of \p Child 1494 static bool isImmediateBase(const CXXRecordDecl *Child, 1495 const CXXRecordDecl *Base) { 1496 assert(Child && "Child must not be null"); 1497 // Note that we do NOT canonicalize the base class here, because 1498 // ASTRecordLayout doesn't either. If that leads us down the wrong path, 1499 // so be it; at least we won't crash. 1500 for (const auto &I : Child->bases()) { 1501 if (I.getType()->getAsCXXRecordDecl() == Base) 1502 return true; 1503 } 1504 1505 return false; 1506 } 1507 1508 static RegionOffset calculateOffset(const MemRegion *R) { 1509 const MemRegion *SymbolicOffsetBase = nullptr; 1510 int64_t Offset = 0; 1511 1512 while (true) { 1513 switch (R->getKind()) { 1514 case MemRegion::CodeSpaceRegionKind: 1515 case MemRegion::StackLocalsSpaceRegionKind: 1516 case MemRegion::StackArgumentsSpaceRegionKind: 1517 case MemRegion::HeapSpaceRegionKind: 1518 case MemRegion::UnknownSpaceRegionKind: 1519 case MemRegion::StaticGlobalSpaceRegionKind: 1520 case MemRegion::GlobalInternalSpaceRegionKind: 1521 case MemRegion::GlobalSystemSpaceRegionKind: 1522 case MemRegion::GlobalImmutableSpaceRegionKind: 1523 // Stores can bind directly to a region space to set a default value. 1524 assert(Offset == 0 && !SymbolicOffsetBase); 1525 goto Finish; 1526 1527 case MemRegion::FunctionCodeRegionKind: 1528 case MemRegion::BlockCodeRegionKind: 1529 case MemRegion::BlockDataRegionKind: 1530 // These will never have bindings, but may end up having values requested 1531 // if the user does some strange casting. 1532 if (Offset != 0) 1533 SymbolicOffsetBase = R; 1534 goto Finish; 1535 1536 case MemRegion::SymbolicRegionKind: 1537 case MemRegion::AllocaRegionKind: 1538 case MemRegion::CompoundLiteralRegionKind: 1539 case MemRegion::CXXThisRegionKind: 1540 case MemRegion::StringRegionKind: 1541 case MemRegion::ObjCStringRegionKind: 1542 case MemRegion::NonParamVarRegionKind: 1543 case MemRegion::ParamVarRegionKind: 1544 case MemRegion::CXXTempObjectRegionKind: 1545 case MemRegion::CXXLifetimeExtendedObjectRegionKind: 1546 // Usual base regions. 1547 goto Finish; 1548 1549 case MemRegion::ObjCIvarRegionKind: 1550 // This is a little strange, but it's a compromise between 1551 // ObjCIvarRegions having unknown compile-time offsets (when using the 1552 // non-fragile runtime) and yet still being distinct, non-overlapping 1553 // regions. Thus we treat them as "like" base regions for the purposes 1554 // of computing offsets. 1555 goto Finish; 1556 1557 case MemRegion::CXXBaseObjectRegionKind: { 1558 const auto *BOR = cast<CXXBaseObjectRegion>(R); 1559 R = BOR->getSuperRegion(); 1560 1561 QualType Ty; 1562 bool RootIsSymbolic = false; 1563 if (const auto *TVR = dyn_cast<TypedValueRegion>(R)) { 1564 Ty = TVR->getDesugaredValueType(R->getContext()); 1565 } else if (const auto *SR = dyn_cast<SymbolicRegion>(R)) { 1566 // If our base region is symbolic, we don't know what type it really is. 1567 // Pretend the type of the symbol is the true dynamic type. 1568 // (This will at least be self-consistent for the life of the symbol.) 1569 Ty = SR->getPointeeStaticType(); 1570 RootIsSymbolic = true; 1571 } 1572 1573 const CXXRecordDecl *Child = Ty->getAsCXXRecordDecl(); 1574 if (!Child) { 1575 // We cannot compute the offset of the base class. 1576 SymbolicOffsetBase = R; 1577 } else { 1578 if (RootIsSymbolic) { 1579 // Base layers on symbolic regions may not be type-correct. 1580 // Double-check the inheritance here, and revert to a symbolic offset 1581 // if it's invalid (e.g. due to a reinterpret_cast). 1582 if (BOR->isVirtual()) { 1583 if (!Child->isVirtuallyDerivedFrom(BOR->getDecl())) 1584 SymbolicOffsetBase = R; 1585 } else { 1586 if (!isImmediateBase(Child, BOR->getDecl())) 1587 SymbolicOffsetBase = R; 1588 } 1589 } 1590 } 1591 1592 // Don't bother calculating precise offsets if we already have a 1593 // symbolic offset somewhere in the chain. 1594 if (SymbolicOffsetBase) 1595 continue; 1596 1597 CharUnits BaseOffset; 1598 const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(Child); 1599 if (BOR->isVirtual()) 1600 BaseOffset = Layout.getVBaseClassOffset(BOR->getDecl()); 1601 else 1602 BaseOffset = Layout.getBaseClassOffset(BOR->getDecl()); 1603 1604 // The base offset is in chars, not in bits. 1605 Offset += BaseOffset.getQuantity() * R->getContext().getCharWidth(); 1606 break; 1607 } 1608 1609 case MemRegion::CXXDerivedObjectRegionKind: { 1610 // TODO: Store the base type in the CXXDerivedObjectRegion and use it. 1611 goto Finish; 1612 } 1613 1614 case MemRegion::ElementRegionKind: { 1615 const auto *ER = cast<ElementRegion>(R); 1616 R = ER->getSuperRegion(); 1617 1618 QualType EleTy = ER->getValueType(); 1619 if (EleTy->isIncompleteType()) { 1620 // We cannot compute the offset of the base class. 1621 SymbolicOffsetBase = R; 1622 continue; 1623 } 1624 1625 SVal Index = ER->getIndex(); 1626 if (std::optional<nonloc::ConcreteInt> CI = 1627 Index.getAs<nonloc::ConcreteInt>()) { 1628 // Don't bother calculating precise offsets if we already have a 1629 // symbolic offset somewhere in the chain. 1630 if (SymbolicOffsetBase) 1631 continue; 1632 1633 int64_t i = CI->getValue()->getSExtValue(); 1634 // This type size is in bits. 1635 Offset += i * R->getContext().getTypeSize(EleTy); 1636 } else { 1637 // We cannot compute offset for non-concrete index. 1638 SymbolicOffsetBase = R; 1639 } 1640 break; 1641 } 1642 case MemRegion::FieldRegionKind: { 1643 const auto *FR = cast<FieldRegion>(R); 1644 R = FR->getSuperRegion(); 1645 assert(R); 1646 1647 const RecordDecl *RD = FR->getDecl()->getParent(); 1648 if (RD->isUnion() || !RD->isCompleteDefinition()) { 1649 // We cannot compute offset for incomplete type. 1650 // For unions, we could treat everything as offset 0, but we'd rather 1651 // treat each field as a symbolic offset so they aren't stored on top 1652 // of each other, since we depend on things in typed regions actually 1653 // matching their types. 1654 SymbolicOffsetBase = R; 1655 } 1656 1657 // Don't bother calculating precise offsets if we already have a 1658 // symbolic offset somewhere in the chain. 1659 if (SymbolicOffsetBase) 1660 continue; 1661 1662 // Get the field number. 1663 unsigned idx = 0; 1664 for (RecordDecl::field_iterator FI = RD->field_begin(), 1665 FE = RD->field_end(); FI != FE; ++FI, ++idx) { 1666 if (FR->getDecl() == *FI) 1667 break; 1668 } 1669 const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(RD); 1670 // This is offset in bits. 1671 Offset += Layout.getFieldOffset(idx); 1672 break; 1673 } 1674 } 1675 } 1676 1677 Finish: 1678 if (SymbolicOffsetBase) 1679 return RegionOffset(SymbolicOffsetBase, RegionOffset::Symbolic); 1680 return RegionOffset(R, Offset); 1681 } 1682 1683 RegionOffset MemRegion::getAsOffset() const { 1684 if (!cachedOffset) 1685 cachedOffset = calculateOffset(this); 1686 return *cachedOffset; 1687 } 1688 1689 //===----------------------------------------------------------------------===// 1690 // BlockDataRegion 1691 //===----------------------------------------------------------------------===// 1692 1693 std::pair<const VarRegion *, const VarRegion *> 1694 BlockDataRegion::getCaptureRegions(const VarDecl *VD) { 1695 MemRegionManager &MemMgr = getMemRegionManager(); 1696 const VarRegion *VR = nullptr; 1697 const VarRegion *OriginalVR = nullptr; 1698 1699 if (!VD->hasAttr<BlocksAttr>() && VD->hasLocalStorage()) { 1700 VR = MemMgr.getNonParamVarRegion(VD, this); 1701 OriginalVR = MemMgr.getVarRegion(VD, LC); 1702 } 1703 else { 1704 if (LC) { 1705 VR = MemMgr.getVarRegion(VD, LC); 1706 OriginalVR = VR; 1707 } 1708 else { 1709 VR = MemMgr.getNonParamVarRegion(VD, MemMgr.getUnknownRegion()); 1710 OriginalVR = MemMgr.getVarRegion(VD, LC); 1711 } 1712 } 1713 return std::make_pair(VR, OriginalVR); 1714 } 1715 1716 void BlockDataRegion::LazyInitializeReferencedVars() { 1717 if (ReferencedVars) 1718 return; 1719 1720 AnalysisDeclContext *AC = getCodeRegion()->getAnalysisDeclContext(); 1721 const auto &ReferencedBlockVars = AC->getReferencedBlockVars(BC->getDecl()); 1722 auto NumBlockVars = 1723 std::distance(ReferencedBlockVars.begin(), ReferencedBlockVars.end()); 1724 1725 if (NumBlockVars == 0) { 1726 ReferencedVars = (void*) 0x1; 1727 return; 1728 } 1729 1730 MemRegionManager &MemMgr = getMemRegionManager(); 1731 llvm::BumpPtrAllocator &A = MemMgr.getAllocator(); 1732 BumpVectorContext BC(A); 1733 1734 using VarVec = BumpVector<const MemRegion *>; 1735 1736 auto *BV = new (A) VarVec(BC, NumBlockVars); 1737 auto *BVOriginal = new (A) VarVec(BC, NumBlockVars); 1738 1739 for (const auto *VD : ReferencedBlockVars) { 1740 const VarRegion *VR = nullptr; 1741 const VarRegion *OriginalVR = nullptr; 1742 std::tie(VR, OriginalVR) = getCaptureRegions(VD); 1743 assert(VR); 1744 assert(OriginalVR); 1745 BV->push_back(VR, BC); 1746 BVOriginal->push_back(OriginalVR, BC); 1747 } 1748 1749 ReferencedVars = BV; 1750 OriginalVars = BVOriginal; 1751 } 1752 1753 BlockDataRegion::referenced_vars_iterator 1754 BlockDataRegion::referenced_vars_begin() const { 1755 const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars(); 1756 1757 auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars); 1758 1759 if (Vec == (void*) 0x1) 1760 return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr); 1761 1762 auto *VecOriginal = 1763 static_cast<BumpVector<const MemRegion *> *>(OriginalVars); 1764 1765 return BlockDataRegion::referenced_vars_iterator(Vec->begin(), 1766 VecOriginal->begin()); 1767 } 1768 1769 BlockDataRegion::referenced_vars_iterator 1770 BlockDataRegion::referenced_vars_end() const { 1771 const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars(); 1772 1773 auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars); 1774 1775 if (Vec == (void*) 0x1) 1776 return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr); 1777 1778 auto *VecOriginal = 1779 static_cast<BumpVector<const MemRegion *> *>(OriginalVars); 1780 1781 return BlockDataRegion::referenced_vars_iterator(Vec->end(), 1782 VecOriginal->end()); 1783 } 1784 1785 llvm::iterator_range<BlockDataRegion::referenced_vars_iterator> 1786 BlockDataRegion::referenced_vars() const { 1787 return llvm::make_range(referenced_vars_begin(), referenced_vars_end()); 1788 } 1789 1790 const VarRegion *BlockDataRegion::getOriginalRegion(const VarRegion *R) const { 1791 for (const auto &I : referenced_vars()) { 1792 if (I.getCapturedRegion() == R) 1793 return I.getOriginalRegion(); 1794 } 1795 return nullptr; 1796 } 1797 1798 //===----------------------------------------------------------------------===// 1799 // RegionAndSymbolInvalidationTraits 1800 //===----------------------------------------------------------------------===// 1801 1802 void RegionAndSymbolInvalidationTraits::setTrait(SymbolRef Sym, 1803 InvalidationKinds IK) { 1804 SymTraitsMap[Sym] |= IK; 1805 } 1806 1807 void RegionAndSymbolInvalidationTraits::setTrait(const MemRegion *MR, 1808 InvalidationKinds IK) { 1809 assert(MR); 1810 if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) 1811 setTrait(SR->getSymbol(), IK); 1812 else 1813 MRTraitsMap[MR] |= IK; 1814 } 1815 1816 bool RegionAndSymbolInvalidationTraits::hasTrait(SymbolRef Sym, 1817 InvalidationKinds IK) const { 1818 const_symbol_iterator I = SymTraitsMap.find(Sym); 1819 if (I != SymTraitsMap.end()) 1820 return I->second & IK; 1821 1822 return false; 1823 } 1824 1825 bool RegionAndSymbolInvalidationTraits::hasTrait(const MemRegion *MR, 1826 InvalidationKinds IK) const { 1827 if (!MR) 1828 return false; 1829 1830 if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) 1831 return hasTrait(SR->getSymbol(), IK); 1832 1833 const_region_iterator I = MRTraitsMap.find(MR); 1834 if (I != MRTraitsMap.end()) 1835 return I->second & IK; 1836 1837 return false; 1838 } 1839