Home | History | Annotate | Download | only in Analysis
      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