]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/Analysis/ProgramPoint.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / Analysis / ProgramPoint.h
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