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/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:
     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               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:
     99   ProgramPoint() {}
    100   ProgramPoint(const void *P,
    101                Kind k,
    102                const LocationContext *l,
    103                const ProgramPointTag *tag = nullptr)
    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)
    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:
    124   const void *getData1() const { return Data1; }
    125   const void *getData2() const { return Data2.getPointer(); }
    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.
    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>
    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>
    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 
    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.
    170   bool isPurgeKind() {
    171     Kind K = getKind();
    172     return (K == PostStmtPurgeDeadSymbolsKind ||
    173             K == PreStmtPurgeDeadSymbolsKind);
    174   }
    175 
    176   const ProgramPointTag *getTag() const { return Tag.getPointer(); }
    177 
    178   const LocationContext *getLocationContext() const {
    179     return L.getPointer();
    180   }
    181 
    182   // For use with DenseMap.  This hash is probably slow.
    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 
    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)
    220     : ProgramPoint(B, BlockEntranceKind, L, tag) {
    221     assert(B && "BlockEntrance requires non-null block");
    222   }
    223 
    224   const CFGBlock *getBlock() const {
    225     return reinterpret_cast<const CFGBlock*>(getData1());
    226   }
    227 
    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;
    235   BlockEntrance() {}
    236   static bool isKind(const ProgramPoint &Location) {
    237     return Location.getKind() == BlockEntranceKind;
    238   }
    239 };
    240 
    241 class BlockExit : public ProgramPoint {
    242 public:
    243   BlockExit(const CFGBlock *B, const LocationContext *L)
    244     : ProgramPoint(B, BlockExitKind, L) {}
    245 
    246   const CFGBlock *getBlock() const {
    247     return reinterpret_cast<const CFGBlock*>(getData1());
    248   }
    249 
    250   const Stmt *getTerminator() const {
    251     return getBlock()->getTerminator();
    252   }
    253 
    254 private:
    255   friend class ProgramPoint;
    256   BlockExit() {}
    257   static bool isKind(const ProgramPoint &Location) {
    258     return Location.getKind() == BlockExitKind;
    259   }
    260 };
    261 
    262 class StmtPoint : public ProgramPoint {
    263 public:
    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 
    270   const Stmt *getStmt() const { return (const Stmt*) getData1(); }
    271 
    272   template <typename T>
    273   const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
    274 
    275 protected:
    276   StmtPoint() {}
    277 private:
    278   friend class ProgramPoint;
    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)
    290     : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
    291 
    292   const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
    293 
    294 private:
    295   friend class ProgramPoint;
    296   PreStmt() {}
    297   static bool isKind(const ProgramPoint &Location) {
    298     return Location.getKind() == PreStmtKind;
    299   }
    300 };
    301 
    302 class PostStmt : public StmtPoint {
    303 protected:
    304   PostStmt() {}
    305   PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
    306            const ProgramPointTag *tag = nullptr)
    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)
    312     : StmtPoint(S, nullptr, k, L, tag) {}
    313 
    314   explicit PostStmt(const Stmt *S, const LocationContext *L,
    315                     const ProgramPointTag *tag = nullptr)
    316     : StmtPoint(S, nullptr, PostStmtKind, L, tag) {}
    317 
    318 private:
    319   friend class ProgramPoint;
    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)
    331     : PostStmt(S, PostConditionKind, L, tag) {}
    332 
    333 private:
    334   friend class ProgramPoint;
    335   PostCondition() {}
    336   static bool isKind(const ProgramPoint &Location) {
    337     return Location.getKind() == PostConditionKind;
    338   }
    339 };
    340 
    341 class LocationCheck : public StmtPoint {
    342 protected:
    343   LocationCheck() {}
    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;
    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)
    360     : LocationCheck(S, L, PreLoadKind, tag) {}
    361 
    362 private:
    363   friend class ProgramPoint;
    364   PreLoad() {}
    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)
    374   : LocationCheck(S, L, PreStoreKind, tag) {}
    375 
    376 private:
    377   friend class ProgramPoint;
    378   PreStore() {}
    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)
    388     : PostStmt(S, PostLoadKind, L, tag) {}
    389 
    390 private:
    391   friend class ProgramPoint;
    392   PostLoad() {}
    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)
    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.
    413   const void *getLocationValue() const {
    414     return getData2();
    415   }
    416 
    417 private:
    418   friend class ProgramPoint;
    419   PostStore() {}
    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)
    429     : PostStmt(S, PostLValueKind, L, tag) {}
    430 
    431 private:
    432   friend class ProgramPoint;
    433   PostLValue() {}
    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)
    445     : StmtPoint(S, nullptr, PreStmtPurgeDeadSymbolsKind, L, tag) { }
    446 
    447 private:
    448   friend class ProgramPoint;
    449   PreStmtPurgeDeadSymbols() {}
    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)
    461     : StmtPoint(S, nullptr, PostStmtPurgeDeadSymbolsKind, L, tag) { }
    462 
    463 private:
    464   friend class ProgramPoint;
    465   PostStmtPurgeDeadSymbols() {}
    466   static bool isKind(const ProgramPoint &Location) {
    467     return Location.getKind() == PostStmtPurgeDeadSymbolsKind;
    468   }
    469 };
    470 
    471 class BlockEdge : public ProgramPoint {
    472 public:
    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 
    479   const CFGBlock *getSrc() const {
    480     return static_cast<const CFGBlock*>(getData1());
    481   }
    482 
    483   const CFGBlock *getDst() const {
    484     return static_cast<const CFGBlock*>(getData2());
    485   }
    486 
    487 private:
    488   friend class ProgramPoint;
    489   BlockEdge() {}
    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.
    502   PostInitializer(const CXXCtorInitializer *I,
    503                   const void *Loc,
    504                   const LocationContext *L)
    505     : ProgramPoint(I, Loc, PostInitializerKind, L) {}
    506 
    507   const CXXCtorInitializer *getInitializer() const {
    508     return static_cast<const CXXCtorInitializer *>(getData1());
    509   }
    510 
    511   /// \brief Returns the location of the field.
    512   const void *getLocationValue() const {
    513     return getData2();
    514   }
    515 
    516 private:
    517   friend class ProgramPoint;
    518   PostInitializer() {}
    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:
    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 
    533   const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); }
    534   SourceLocation getLocation() const {
    535     return SourceLocation::getFromPtrEncoding(getData1());
    536   }
    537 
    538 protected:
    539   ImplicitCallPoint() {}
    540 private:
    541   friend class ProgramPoint;
    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)
    555     : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {}
    556 
    557 private:
    558   friend class ProgramPoint;
    559   PreImplicitCall() {}
    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)
    572     : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {}
    573 
    574 private:
    575   friend class ProgramPoint;
    576   PostImplicitCall() {}
    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:
    586   CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
    587             const LocationContext *callerCtx)
    588     : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, nullptr) {}
    589 
    590   const Stmt *getCallExpr() const {
    591     return static_cast<const Stmt *>(getData1());
    592   }
    593 
    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.
    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;
    607   CallEnter() {}
    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.
    625   CallExitBegin(const StackFrameContext *L, const ReturnStmt *RS)
    626     : ProgramPoint(RS, CallExitBeginKind, L, nullptr) { }
    627 
    628 private:
    629   friend class ProgramPoint;
    630   CallExitBegin() {}
    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.
    641   CallExitEnd(const StackFrameContext *CalleeCtx,
    642               const LocationContext *CallerCtx)
    643     : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, nullptr) {}
    644 
    645   const StackFrameContext *getCalleeContext() const {
    646     return static_cast<const StackFrameContext *>(getData1());
    647   }
    648 
    649 private:
    650   friend class ProgramPoint;
    651   CallExitEnd() {}
    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)
    664     : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {}
    665 
    666   const void *getData() const { return getData1(); }
    667 
    668 private:
    669   friend class ProgramPoint;
    670   EpsilonPoint() {}
    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