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