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