1 //==- ProgramPoint.h - Program Points for Path-Sensitive 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 the interface ProgramPoint, which identifies a 11 // distinct location in a function. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H 16 #define LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H 17 18 #include "clang/Analysis/AnalysisDeclContext.h" 19 #include "clang/Analysis/CFG.h" 20 #include "llvm/ADT/DenseMap.h" 21 #include "llvm/ADT/FoldingSet.h" 22 #include "llvm/ADT/Optional.h" 23 #include "llvm/ADT/PointerIntPair.h" 24 #include "llvm/ADT/StringRef.h" 25 #include "llvm/Support/Casting.h" 26 #include "llvm/Support/DataTypes.h" 27 #include <cassert> 28 #include <string> 29 #include <utility> 30 31 namespace clang { 32 33 class AnalysisDeclContext; 34 class FunctionDecl; 35 class LocationContext; 36 37 /// ProgramPoints can be "tagged" as representing points specific to a given 38 /// analysis entity. Tags are abstract annotations, with an associated 39 /// description and potentially other information. 40 class ProgramPointTag { 41 public: 42 ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {} 43 virtual ~ProgramPointTag(); 44 virtual StringRef getTagDescription() const = 0; 45 46 protected: 47 /// Used to implement 'isKind' in subclasses. 48 const void *getTagKind() { return TagKind; } 49 50 private: 51 const void *TagKind; 52 }; 53 54 class SimpleProgramPointTag : public ProgramPointTag { 55 std::string Desc; 56 public: 57 SimpleProgramPointTag(StringRef MsgProvider, StringRef Msg); 58 StringRef getTagDescription() const override; 59 }; 60 61 class ProgramPoint { 62 public: 63 enum Kind { BlockEdgeKind, 64 BlockEntranceKind, 65 BlockExitKind, 66 PreStmtKind, 67 PreStmtPurgeDeadSymbolsKind, 68 PostStmtPurgeDeadSymbolsKind, 69 PostStmtKind, 70 PreLoadKind, 71 PostLoadKind, 72 PreStoreKind, 73 PostStoreKind, 74 PostConditionKind, 75 PostLValueKind, 76 MinPostStmtKind = PostStmtKind, 77 MaxPostStmtKind = PostLValueKind, 78 PostInitializerKind, 79 CallEnterKind, 80 CallExitBeginKind, 81 CallExitEndKind, 82 PreImplicitCallKind, 83 PostImplicitCallKind, 84 MinImplicitCallKind = PreImplicitCallKind, 85 MaxImplicitCallKind = PostImplicitCallKind, 86 LoopExitKind, 87 EpsilonKind}; 88 89 private: 90 const void *Data1; 91 llvm::PointerIntPair<const void *, 2, unsigned> Data2; 92 93 // The LocationContext could be NULL to allow ProgramPoint to be used in 94 // context insensitive analysis. 95 llvm::PointerIntPair<const LocationContext *, 2, unsigned> L; 96 97 llvm::PointerIntPair<const ProgramPointTag *, 2, unsigned> Tag; 98 99 protected: 100 ProgramPoint() {} 101 ProgramPoint(const void *P, 102 Kind k, 103 const LocationContext *l, 104 const ProgramPointTag *tag = nullptr) 105 : Data1(P), 106 Data2(nullptr, (((unsigned) k) >> 0) & 0x3), 107 L(l, (((unsigned) k) >> 2) & 0x3), 108 Tag(tag, (((unsigned) k) >> 4) & 0x3) { 109 assert(getKind() == k); 110 assert(getLocationContext() == l); 111 assert(getData1() == P); 112 } 113 114 ProgramPoint(const void *P1, 115 const void *P2, 116 Kind k, 117 const LocationContext *l, 118 const ProgramPointTag *tag = nullptr) 119 : Data1(P1), 120 Data2(P2, (((unsigned) k) >> 0) & 0x3), 121 L(l, (((unsigned) k) >> 2) & 0x3), 122 Tag(tag, (((unsigned) k) >> 4) & 0x3) {} 123 124 protected: 125 const void *getData1() const { return Data1; } 126 const void *getData2() const { return Data2.getPointer(); } 127 void setData2(const void *d) { Data2.setPointer(d); } 128 129 public: 130 /// Create a new ProgramPoint object that is the same as the original 131 /// except for using the specified tag value. 132 ProgramPoint withTag(const ProgramPointTag *tag) const { 133 return ProgramPoint(getData1(), getData2(), getKind(), 134 getLocationContext(), tag); 135 } 136 137 /// \brief Convert to the specified ProgramPoint type, asserting that this 138 /// ProgramPoint is of the desired type. 139 template<typename T> 140 T castAs() const { 141 assert(T::isKind(*this)); 142 T t; 143 ProgramPoint& PP = t; 144 PP = *this; 145 return t; 146 } 147 148 /// \brief Convert to the specified ProgramPoint type, returning None if this 149 /// ProgramPoint is not of the desired type. 150 template<typename T> 151 Optional<T> getAs() const { 152 if (!T::isKind(*this)) 153 return None; 154 T t; 155 ProgramPoint& PP = t; 156 PP = *this; 157 return t; 158 } 159 160 Kind getKind() const { 161 unsigned x = Tag.getInt(); 162 x <<= 2; 163 x |= L.getInt(); 164 x <<= 2; 165 x |= Data2.getInt(); 166 return (Kind) x; 167 } 168 169 /// \brief Is this a program point corresponding to purge/removal of dead 170 /// symbols and bindings. 171 bool isPurgeKind() { 172 Kind K = getKind(); 173 return (K == PostStmtPurgeDeadSymbolsKind || 174 K == PreStmtPurgeDeadSymbolsKind); 175 } 176 177 const ProgramPointTag *getTag() const { return Tag.getPointer(); } 178 179 const LocationContext *getLocationContext() const { 180 return L.getPointer(); 181 } 182 183 // For use with DenseMap. This hash is probably slow. 184 unsigned getHashValue() const { 185 llvm::FoldingSetNodeID ID; 186 Profile(ID); 187 return ID.ComputeHash(); 188 } 189 190 bool operator==(const ProgramPoint & RHS) const { 191 return Data1 == RHS.Data1 && 192 Data2 == RHS.Data2 && 193 L == RHS.L && 194 Tag == RHS.Tag; 195 } 196 197 bool operator!=(const ProgramPoint &RHS) const { 198 return Data1 != RHS.Data1 || 199 Data2 != RHS.Data2 || 200 L != RHS.L || 201 Tag != RHS.Tag; 202 } 203 204 void Profile(llvm::FoldingSetNodeID& ID) const { 205 ID.AddInteger((unsigned) getKind()); 206 ID.AddPointer(getData1()); 207 ID.AddPointer(getData2()); 208 ID.AddPointer(getLocationContext()); 209 ID.AddPointer(getTag()); 210 } 211 212 static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K, 213 const LocationContext *LC, 214 const ProgramPointTag *tag); 215 }; 216 217 class BlockEntrance : public ProgramPoint { 218 public: 219 BlockEntrance(const CFGBlock *B, const LocationContext *L, 220 const ProgramPointTag *tag = nullptr) 221 : ProgramPoint(B, BlockEntranceKind, L, tag) { 222 assert(B && "BlockEntrance requires non-null block"); 223 } 224 225 const CFGBlock *getBlock() const { 226 return reinterpret_cast<const CFGBlock*>(getData1()); 227 } 228 229 Optional<CFGElement> getFirstElement() const { 230 const CFGBlock *B = getBlock(); 231 return B->empty() ? Optional<CFGElement>() : B->front(); 232 } 233 234 private: 235 friend class ProgramPoint; 236 BlockEntrance() {} 237 static bool isKind(const ProgramPoint &Location) { 238 return Location.getKind() == BlockEntranceKind; 239 } 240 }; 241 242 class BlockExit : public ProgramPoint { 243 public: 244 BlockExit(const CFGBlock *B, const LocationContext *L) 245 : ProgramPoint(B, BlockExitKind, L) {} 246 247 const CFGBlock *getBlock() const { 248 return reinterpret_cast<const CFGBlock*>(getData1()); 249 } 250 251 const Stmt *getTerminator() const { 252 return getBlock()->getTerminator(); 253 } 254 255 private: 256 friend class ProgramPoint; 257 BlockExit() {} 258 static bool isKind(const ProgramPoint &Location) { 259 return Location.getKind() == BlockExitKind; 260 } 261 }; 262 263 class StmtPoint : public ProgramPoint { 264 public: 265 StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L, 266 const ProgramPointTag *tag) 267 : ProgramPoint(S, p2, k, L, tag) { 268 assert(S); 269 } 270 271 const Stmt *getStmt() const { return (const Stmt*) getData1(); } 272 273 template <typename T> 274 const T* getStmtAs() const { return dyn_cast<T>(getStmt()); } 275 276 protected: 277 StmtPoint() {} 278 private: 279 friend class ProgramPoint; 280 static bool isKind(const ProgramPoint &Location) { 281 unsigned k = Location.getKind(); 282 return k >= PreStmtKind && k <= MaxPostStmtKind; 283 } 284 }; 285 286 287 class PreStmt : public StmtPoint { 288 public: 289 PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag, 290 const Stmt *SubStmt = nullptr) 291 : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {} 292 293 const Stmt *getSubStmt() const { return (const Stmt*) getData2(); } 294 295 private: 296 friend class ProgramPoint; 297 PreStmt() {} 298 static bool isKind(const ProgramPoint &Location) { 299 return Location.getKind() == PreStmtKind; 300 } 301 }; 302 303 class PostStmt : public StmtPoint { 304 protected: 305 PostStmt() {} 306 PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L, 307 const ProgramPointTag *tag = nullptr) 308 : StmtPoint(S, data, k, L, tag) {} 309 310 public: 311 explicit PostStmt(const Stmt *S, Kind k, const LocationContext *L, 312 const ProgramPointTag *tag = nullptr) 313 : StmtPoint(S, nullptr, k, L, tag) {} 314 315 explicit PostStmt(const Stmt *S, const LocationContext *L, 316 const ProgramPointTag *tag = nullptr) 317 : StmtPoint(S, nullptr, PostStmtKind, L, tag) {} 318 319 private: 320 friend class ProgramPoint; 321 static bool isKind(const ProgramPoint &Location) { 322 unsigned k = Location.getKind(); 323 return k >= MinPostStmtKind && k <= MaxPostStmtKind; 324 } 325 }; 326 327 // PostCondition represents the post program point of a branch condition. 328 class PostCondition : public PostStmt { 329 public: 330 PostCondition(const Stmt *S, const LocationContext *L, 331 const ProgramPointTag *tag = nullptr) 332 : PostStmt(S, PostConditionKind, L, tag) {} 333 334 private: 335 friend class ProgramPoint; 336 PostCondition() {} 337 static bool isKind(const ProgramPoint &Location) { 338 return Location.getKind() == PostConditionKind; 339 } 340 }; 341 342 class LocationCheck : public StmtPoint { 343 protected: 344 LocationCheck() {} 345 LocationCheck(const Stmt *S, const LocationContext *L, 346 ProgramPoint::Kind K, const ProgramPointTag *tag) 347 : StmtPoint(S, nullptr, K, L, tag) {} 348 349 private: 350 friend class ProgramPoint; 351 static bool isKind(const ProgramPoint &location) { 352 unsigned k = location.getKind(); 353 return k == PreLoadKind || k == PreStoreKind; 354 } 355 }; 356 357 class PreLoad : public LocationCheck { 358 public: 359 PreLoad(const Stmt *S, const LocationContext *L, 360 const ProgramPointTag *tag = nullptr) 361 : LocationCheck(S, L, PreLoadKind, tag) {} 362 363 private: 364 friend class ProgramPoint; 365 PreLoad() {} 366 static bool isKind(const ProgramPoint &location) { 367 return location.getKind() == PreLoadKind; 368 } 369 }; 370 371 class PreStore : public LocationCheck { 372 public: 373 PreStore(const Stmt *S, const LocationContext *L, 374 const ProgramPointTag *tag = nullptr) 375 : LocationCheck(S, L, PreStoreKind, tag) {} 376 377 private: 378 friend class ProgramPoint; 379 PreStore() {} 380 static bool isKind(const ProgramPoint &location) { 381 return location.getKind() == PreStoreKind; 382 } 383 }; 384 385 class PostLoad : public PostStmt { 386 public: 387 PostLoad(const Stmt *S, const LocationContext *L, 388 const ProgramPointTag *tag = nullptr) 389 : PostStmt(S, PostLoadKind, L, tag) {} 390 391 private: 392 friend class ProgramPoint; 393 PostLoad() {} 394 static bool isKind(const ProgramPoint &Location) { 395 return Location.getKind() == PostLoadKind; 396 } 397 }; 398 399 /// \brief Represents a program point after a store evaluation. 400 class PostStore : public PostStmt { 401 public: 402 /// Construct the post store point. 403 /// \param Loc can be used to store the information about the location 404 /// used in the form it was uttered in the code. 405 PostStore(const Stmt *S, const LocationContext *L, const void *Loc, 406 const ProgramPointTag *tag = nullptr) 407 : PostStmt(S, PostStoreKind, L, tag) { 408 assert(getData2() == nullptr); 409 setData2(Loc); 410 } 411 412 /// \brief Returns the information about the location used in the store, 413 /// how it was uttered in the code. 414 const void *getLocationValue() const { 415 return getData2(); 416 } 417 418 private: 419 friend class ProgramPoint; 420 PostStore() {} 421 static bool isKind(const ProgramPoint &Location) { 422 return Location.getKind() == PostStoreKind; 423 } 424 }; 425 426 class PostLValue : public PostStmt { 427 public: 428 PostLValue(const Stmt *S, const LocationContext *L, 429 const ProgramPointTag *tag = nullptr) 430 : PostStmt(S, PostLValueKind, L, tag) {} 431 432 private: 433 friend class ProgramPoint; 434 PostLValue() {} 435 static bool isKind(const ProgramPoint &Location) { 436 return Location.getKind() == PostLValueKind; 437 } 438 }; 439 440 /// Represents a point after we ran remove dead bindings BEFORE 441 /// processing the given statement. 442 class PreStmtPurgeDeadSymbols : public StmtPoint { 443 public: 444 PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L, 445 const ProgramPointTag *tag = nullptr) 446 : StmtPoint(S, nullptr, PreStmtPurgeDeadSymbolsKind, L, tag) { } 447 448 private: 449 friend class ProgramPoint; 450 PreStmtPurgeDeadSymbols() {} 451 static bool isKind(const ProgramPoint &Location) { 452 return Location.getKind() == PreStmtPurgeDeadSymbolsKind; 453 } 454 }; 455 456 /// Represents a point after we ran remove dead bindings AFTER 457 /// processing the given statement. 458 class PostStmtPurgeDeadSymbols : public StmtPoint { 459 public: 460 PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L, 461 const ProgramPointTag *tag = nullptr) 462 : StmtPoint(S, nullptr, PostStmtPurgeDeadSymbolsKind, L, tag) { } 463 464 private: 465 friend class ProgramPoint; 466 PostStmtPurgeDeadSymbols() {} 467 static bool isKind(const ProgramPoint &Location) { 468 return Location.getKind() == PostStmtPurgeDeadSymbolsKind; 469 } 470 }; 471 472 class BlockEdge : public ProgramPoint { 473 public: 474 BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L) 475 : ProgramPoint(B1, B2, BlockEdgeKind, L) { 476 assert(B1 && "BlockEdge: source block must be non-null"); 477 assert(B2 && "BlockEdge: destination block must be non-null"); 478 } 479 480 const CFGBlock *getSrc() const { 481 return static_cast<const CFGBlock*>(getData1()); 482 } 483 484 const CFGBlock *getDst() const { 485 return static_cast<const CFGBlock*>(getData2()); 486 } 487 488 private: 489 friend class ProgramPoint; 490 BlockEdge() {} 491 static bool isKind(const ProgramPoint &Location) { 492 return Location.getKind() == BlockEdgeKind; 493 } 494 }; 495 496 class PostInitializer : public ProgramPoint { 497 public: 498 /// \brief Construct a PostInitializer point that represents a location after 499 /// CXXCtorInitializer expression evaluation. 500 /// 501 /// \param I The initializer. 502 /// \param Loc The location of the field being initialized. 503 PostInitializer(const CXXCtorInitializer *I, 504 const void *Loc, 505 const LocationContext *L) 506 : ProgramPoint(I, Loc, PostInitializerKind, L) {} 507 508 const CXXCtorInitializer *getInitializer() const { 509 return static_cast<const CXXCtorInitializer *>(getData1()); 510 } 511 512 /// \brief Returns the location of the field. 513 const void *getLocationValue() const { 514 return getData2(); 515 } 516 517 private: 518 friend class ProgramPoint; 519 PostInitializer() {} 520 static bool isKind(const ProgramPoint &Location) { 521 return Location.getKind() == PostInitializerKind; 522 } 523 }; 524 525 /// Represents an implicit call event. 526 /// 527 /// The nearest statement is provided for diagnostic purposes. 528 class ImplicitCallPoint : public ProgramPoint { 529 public: 530 ImplicitCallPoint(const Decl *D, SourceLocation Loc, Kind K, 531 const LocationContext *L, const ProgramPointTag *Tag) 532 : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag) {} 533 534 const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); } 535 SourceLocation getLocation() const { 536 return SourceLocation::getFromPtrEncoding(getData1()); 537 } 538 539 protected: 540 ImplicitCallPoint() {} 541 private: 542 friend class ProgramPoint; 543 static bool isKind(const ProgramPoint &Location) { 544 return Location.getKind() >= MinImplicitCallKind && 545 Location.getKind() <= MaxImplicitCallKind; 546 } 547 }; 548 549 /// Represents a program point just before an implicit call event. 550 /// 551 /// Explicit calls will appear as PreStmt program points. 552 class PreImplicitCall : public ImplicitCallPoint { 553 public: 554 PreImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L, 555 const ProgramPointTag *Tag = nullptr) 556 : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {} 557 558 private: 559 friend class ProgramPoint; 560 PreImplicitCall() {} 561 static bool isKind(const ProgramPoint &Location) { 562 return Location.getKind() == PreImplicitCallKind; 563 } 564 }; 565 566 /// Represents a program point just after an implicit call event. 567 /// 568 /// Explicit calls will appear as PostStmt program points. 569 class PostImplicitCall : public ImplicitCallPoint { 570 public: 571 PostImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L, 572 const ProgramPointTag *Tag = nullptr) 573 : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {} 574 575 private: 576 friend class ProgramPoint; 577 PostImplicitCall() {} 578 static bool isKind(const ProgramPoint &Location) { 579 return Location.getKind() == PostImplicitCallKind; 580 } 581 }; 582 583 /// Represents a point when we begin processing an inlined call. 584 /// CallEnter uses the caller's location context. 585 class CallEnter : public ProgramPoint { 586 public: 587 CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx, 588 const LocationContext *callerCtx) 589 : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, nullptr) {} 590 591 const Stmt *getCallExpr() const { 592 return static_cast<const Stmt *>(getData1()); 593 } 594 595 const StackFrameContext *getCalleeContext() const { 596 return static_cast<const StackFrameContext *>(getData2()); 597 } 598 599 /// Returns the entry block in the CFG for the entered function. 600 const CFGBlock *getEntry() const { 601 const StackFrameContext *CalleeCtx = getCalleeContext(); 602 const CFG *CalleeCFG = CalleeCtx->getCFG(); 603 return &(CalleeCFG->getEntry()); 604 } 605 606 private: 607 friend class ProgramPoint; 608 CallEnter() {} 609 static bool isKind(const ProgramPoint &Location) { 610 return Location.getKind() == CallEnterKind; 611 } 612 }; 613 614 /// Represents a point when we start the call exit sequence (for inlined call). 615 /// 616 /// The call exit is simulated with a sequence of nodes, which occur between 617 /// CallExitBegin and CallExitEnd. The following operations occur between the 618 /// two program points: 619 /// - CallExitBegin 620 /// - Bind the return value 621 /// - Run Remove dead bindings (to clean up the dead symbols from the callee). 622 /// - CallExitEnd 623 class CallExitBegin : public ProgramPoint { 624 public: 625 // CallExitBegin uses the callee's location context. 626 CallExitBegin(const StackFrameContext *L, const ReturnStmt *RS) 627 : ProgramPoint(RS, CallExitBeginKind, L, nullptr) { } 628 629 private: 630 friend class ProgramPoint; 631 CallExitBegin() {} 632 static bool isKind(const ProgramPoint &Location) { 633 return Location.getKind() == CallExitBeginKind; 634 } 635 }; 636 637 /// Represents a point when we finish the call exit sequence (for inlined call). 638 /// \sa CallExitBegin 639 class CallExitEnd : public ProgramPoint { 640 public: 641 // CallExitEnd uses the caller's location context. 642 CallExitEnd(const StackFrameContext *CalleeCtx, 643 const LocationContext *CallerCtx) 644 : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, nullptr) {} 645 646 const StackFrameContext *getCalleeContext() const { 647 return static_cast<const StackFrameContext *>(getData1()); 648 } 649 650 private: 651 friend class ProgramPoint; 652 CallExitEnd() {} 653 static bool isKind(const ProgramPoint &Location) { 654 return Location.getKind() == CallExitEndKind; 655 } 656 }; 657 658 /// Represents a point when we exit a loop. 659 /// When this ProgramPoint is encountered we can be sure that the symbolic 660 /// execution of the corresponding LoopStmt is finished on the given path. 661 /// Note: It is possible to encounter a LoopExit element when we haven't even 662 /// encountered the loop itself. At the current state not all loop exits will 663 /// result in a LoopExit program point. 664 class LoopExit : public ProgramPoint { 665 public: 666 LoopExit(const Stmt *LoopStmt, const LocationContext *LC) 667 : ProgramPoint(LoopStmt, nullptr, LoopExitKind, LC) {} 668 669 const Stmt *getLoopStmt() const { 670 return static_cast<const Stmt *>(getData1()); 671 } 672 673 private: 674 friend class ProgramPoint; 675 LoopExit() {} 676 static bool isKind(const ProgramPoint &Location) { 677 return Location.getKind() == LoopExitKind; 678 } 679 }; 680 681 /// This is a meta program point, which should be skipped by all the diagnostic 682 /// reasoning etc. 683 class EpsilonPoint : public ProgramPoint { 684 public: 685 EpsilonPoint(const LocationContext *L, const void *Data1, 686 const void *Data2 = nullptr, 687 const ProgramPointTag *tag = nullptr) 688 : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {} 689 690 const void *getData() const { return getData1(); } 691 692 private: 693 friend class ProgramPoint; 694 EpsilonPoint() {} 695 static bool isKind(const ProgramPoint &Location) { 696 return Location.getKind() == EpsilonKind; 697 } 698 }; 699 700 } // end namespace clang 701 702 703 namespace llvm { // Traits specialization for DenseMap 704 705 template <> struct DenseMapInfo<clang::ProgramPoint> { 706 707 static inline clang::ProgramPoint getEmptyKey() { 708 uintptr_t x = 709 reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7; 710 return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr); 711 } 712 713 static inline clang::ProgramPoint getTombstoneKey() { 714 uintptr_t x = 715 reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7; 716 return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr); 717 } 718 719 static unsigned getHashValue(const clang::ProgramPoint &Loc) { 720 return Loc.getHashValue(); 721 } 722 723 static bool isEqual(const clang::ProgramPoint &L, 724 const clang::ProgramPoint &R) { 725 return L == R; 726 } 727 728 }; 729 730 template <> 731 struct isPodLike<clang::ProgramPoint> { static const bool value = true; }; 732 733 } // end namespace llvm 734 735 #endif 736