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