• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_PROGRAM_POINT
16 #define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
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 class ProgramPointTag;
37 
38 class ProgramPoint {
39 public:
40   enum Kind { BlockEdgeKind,
41               BlockEntranceKind,
42               BlockExitKind,
43               PreStmtKind,
44               PreStmtPurgeDeadSymbolsKind,
45               PostStmtPurgeDeadSymbolsKind,
46               PostStmtKind,
47               PreLoadKind,
48               PostLoadKind,
49               PreStoreKind,
50               PostStoreKind,
51               PostConditionKind,
52               PostLValueKind,
53               MinPostStmtKind = PostStmtKind,
54               MaxPostStmtKind = PostLValueKind,
55               PostInitializerKind,
56               CallEnterKind,
57               CallExitBeginKind,
58               CallExitEndKind,
59               PreImplicitCallKind,
60               PostImplicitCallKind,
61               MinImplicitCallKind = PreImplicitCallKind,
62               MaxImplicitCallKind = PostImplicitCallKind,
63               EpsilonKind};
64 
65 private:
66   const void *Data1;
67   llvm::PointerIntPair<const void *, 2, unsigned> Data2;
68 
69   // The LocationContext could be NULL to allow ProgramPoint to be used in
70   // context insensitive analysis.
71   llvm::PointerIntPair<const LocationContext *, 2, unsigned> L;
72 
73   llvm::PointerIntPair<const ProgramPointTag *, 2, unsigned> Tag;
74 
75 protected:
ProgramPoint()76   ProgramPoint() {}
77   ProgramPoint(const void *P,
78                Kind k,
79                const LocationContext *l,
80                const ProgramPointTag *tag = 0)
Data1(P)81     : Data1(P),
82       Data2(0, (((unsigned) k) >> 0) & 0x3),
83       L(l, (((unsigned) k) >> 2) & 0x3),
84       Tag(tag, (((unsigned) k) >> 4) & 0x3) {
85         assert(getKind() == k);
86         assert(getLocationContext() == l);
87         assert(getData1() == P);
88       }
89 
90   ProgramPoint(const void *P1,
91                const void *P2,
92                Kind k,
93                const LocationContext *l,
94                const ProgramPointTag *tag = 0)
Data1(P1)95     : Data1(P1),
96       Data2(P2, (((unsigned) k) >> 0) & 0x3),
97       L(l, (((unsigned) k) >> 2) & 0x3),
98       Tag(tag, (((unsigned) k) >> 4) & 0x3) {}
99 
100 protected:
getData1()101   const void *getData1() const { return Data1; }
getData2()102   const void *getData2() const { return Data2.getPointer(); }
setData2(const void * d)103   void setData2(const void *d) { Data2.setPointer(d); }
104 
105 public:
106   /// Create a new ProgramPoint object that is the same as the original
107   /// except for using the specified tag value.
withTag(const ProgramPointTag * tag)108   ProgramPoint withTag(const ProgramPointTag *tag) const {
109     return ProgramPoint(getData1(), getData2(), getKind(),
110                         getLocationContext(), tag);
111   }
112 
113   /// \brief Convert to the specified ProgramPoint type, asserting that this
114   /// ProgramPoint is of the desired type.
115   template<typename T>
castAs()116   T castAs() const {
117     assert(T::isKind(*this));
118     T t;
119     ProgramPoint& PP = t;
120     PP = *this;
121     return t;
122   }
123 
124   /// \brief Convert to the specified ProgramPoint type, returning None if this
125   /// ProgramPoint is not of the desired type.
126   template<typename T>
getAs()127   Optional<T> getAs() const {
128     if (!T::isKind(*this))
129       return None;
130     T t;
131     ProgramPoint& PP = t;
132     PP = *this;
133     return t;
134   }
135 
getKind()136   Kind getKind() const {
137     unsigned x = Tag.getInt();
138     x <<= 2;
139     x |= L.getInt();
140     x <<= 2;
141     x |= Data2.getInt();
142     return (Kind) x;
143   }
144 
145   /// \brief Is this a program point corresponding to purge/removal of dead
146   /// symbols and bindings.
isPurgeKind()147   bool isPurgeKind() {
148     Kind K = getKind();
149     return (K == PostStmtPurgeDeadSymbolsKind ||
150             K == PreStmtPurgeDeadSymbolsKind);
151   }
152 
getTag()153   const ProgramPointTag *getTag() const { return Tag.getPointer(); }
154 
getLocationContext()155   const LocationContext *getLocationContext() const {
156     return L.getPointer();
157   }
158 
159   // For use with DenseMap.  This hash is probably slow.
getHashValue()160   unsigned getHashValue() const {
161     llvm::FoldingSetNodeID ID;
162     Profile(ID);
163     return ID.ComputeHash();
164   }
165 
166   bool operator==(const ProgramPoint & RHS) const {
167     return Data1 == RHS.Data1 &&
168            Data2 == RHS.Data2 &&
169            L == RHS.L &&
170            Tag == RHS.Tag;
171   }
172 
173   bool operator!=(const ProgramPoint &RHS) const {
174     return Data1 != RHS.Data1 ||
175            Data2 != RHS.Data2 ||
176            L != RHS.L ||
177            Tag != RHS.Tag;
178   }
179 
Profile(llvm::FoldingSetNodeID & ID)180   void Profile(llvm::FoldingSetNodeID& ID) const {
181     ID.AddInteger((unsigned) getKind());
182     ID.AddPointer(getData1());
183     ID.AddPointer(getData2());
184     ID.AddPointer(getLocationContext());
185     ID.AddPointer(getTag());
186   }
187 
188   static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
189                                       const LocationContext *LC,
190                                       const ProgramPointTag *tag);
191 };
192 
193 class BlockEntrance : public ProgramPoint {
194 public:
195   BlockEntrance(const CFGBlock *B, const LocationContext *L,
196                 const ProgramPointTag *tag = 0)
ProgramPoint(B,BlockEntranceKind,L,tag)197     : ProgramPoint(B, BlockEntranceKind, L, tag) {
198     assert(B && "BlockEntrance requires non-null block");
199   }
200 
getBlock()201   const CFGBlock *getBlock() const {
202     return reinterpret_cast<const CFGBlock*>(getData1());
203   }
204 
getFirstElement()205   Optional<CFGElement> getFirstElement() const {
206     const CFGBlock *B = getBlock();
207     return B->empty() ? Optional<CFGElement>() : B->front();
208   }
209 
210 private:
211   friend class ProgramPoint;
BlockEntrance()212   BlockEntrance() {}
isKind(const ProgramPoint & Location)213   static bool isKind(const ProgramPoint &Location) {
214     return Location.getKind() == BlockEntranceKind;
215   }
216 };
217 
218 class BlockExit : public ProgramPoint {
219 public:
BlockExit(const CFGBlock * B,const LocationContext * L)220   BlockExit(const CFGBlock *B, const LocationContext *L)
221     : ProgramPoint(B, BlockExitKind, L) {}
222 
getBlock()223   const CFGBlock *getBlock() const {
224     return reinterpret_cast<const CFGBlock*>(getData1());
225   }
226 
getTerminator()227   const Stmt *getTerminator() const {
228     return getBlock()->getTerminator();
229   }
230 
231 private:
232   friend class ProgramPoint;
BlockExit()233   BlockExit() {}
isKind(const ProgramPoint & Location)234   static bool isKind(const ProgramPoint &Location) {
235     return Location.getKind() == BlockExitKind;
236   }
237 };
238 
239 class StmtPoint : public ProgramPoint {
240 public:
StmtPoint(const Stmt * S,const void * p2,Kind k,const LocationContext * L,const ProgramPointTag * tag)241   StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
242             const ProgramPointTag *tag)
243     : ProgramPoint(S, p2, k, L, tag) {
244     assert(S);
245   }
246 
getStmt()247   const Stmt *getStmt() const { return (const Stmt*) getData1(); }
248 
249   template <typename T>
getStmtAs()250   const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
251 
252 protected:
StmtPoint()253   StmtPoint() {}
254 private:
255   friend class ProgramPoint;
isKind(const ProgramPoint & Location)256   static bool isKind(const ProgramPoint &Location) {
257     unsigned k = Location.getKind();
258     return k >= PreStmtKind && k <= MaxPostStmtKind;
259   }
260 };
261 
262 
263 class PreStmt : public StmtPoint {
264 public:
265   PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag,
266           const Stmt *SubStmt = 0)
StmtPoint(S,SubStmt,PreStmtKind,L,tag)267     : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
268 
getSubStmt()269   const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
270 
271 private:
272   friend class ProgramPoint;
PreStmt()273   PreStmt() {}
isKind(const ProgramPoint & Location)274   static bool isKind(const ProgramPoint &Location) {
275     return Location.getKind() == PreStmtKind;
276   }
277 };
278 
279 class PostStmt : public StmtPoint {
280 protected:
PostStmt()281   PostStmt() {}
282   PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
283            const ProgramPointTag *tag = 0)
StmtPoint(S,data,k,L,tag)284     : StmtPoint(S, data, k, L, tag) {}
285 
286 public:
287   explicit PostStmt(const Stmt *S, Kind k,
288                     const LocationContext *L, const ProgramPointTag *tag = 0)
StmtPoint(S,NULL,k,L,tag)289     : StmtPoint(S, NULL, k, L, tag) {}
290 
291   explicit PostStmt(const Stmt *S, const LocationContext *L,
292                     const ProgramPointTag *tag = 0)
StmtPoint(S,NULL,PostStmtKind,L,tag)293     : StmtPoint(S, NULL, PostStmtKind, L, tag) {}
294 
295 private:
296   friend class ProgramPoint;
isKind(const ProgramPoint & Location)297   static bool isKind(const ProgramPoint &Location) {
298     unsigned k = Location.getKind();
299     return k >= MinPostStmtKind && k <= MaxPostStmtKind;
300   }
301 };
302 
303 // PostCondition represents the post program point of a branch condition.
304 class PostCondition : public PostStmt {
305 public:
306   PostCondition(const Stmt *S, const LocationContext *L,
307                 const ProgramPointTag *tag = 0)
PostStmt(S,PostConditionKind,L,tag)308     : PostStmt(S, PostConditionKind, L, tag) {}
309 
310 private:
311   friend class ProgramPoint;
PostCondition()312   PostCondition() {}
isKind(const ProgramPoint & Location)313   static bool isKind(const ProgramPoint &Location) {
314     return Location.getKind() == PostConditionKind;
315   }
316 };
317 
318 class LocationCheck : public StmtPoint {
319 protected:
LocationCheck()320   LocationCheck() {}
LocationCheck(const Stmt * S,const LocationContext * L,ProgramPoint::Kind K,const ProgramPointTag * tag)321   LocationCheck(const Stmt *S, const LocationContext *L,
322                 ProgramPoint::Kind K, const ProgramPointTag *tag)
323     : StmtPoint(S, NULL, K, L, tag) {}
324 
325 private:
326   friend class ProgramPoint;
isKind(const ProgramPoint & location)327   static bool isKind(const ProgramPoint &location) {
328     unsigned k = location.getKind();
329     return k == PreLoadKind || k == PreStoreKind;
330   }
331 };
332 
333 class PreLoad : public LocationCheck {
334 public:
335   PreLoad(const Stmt *S, const LocationContext *L,
336           const ProgramPointTag *tag = 0)
LocationCheck(S,L,PreLoadKind,tag)337     : LocationCheck(S, L, PreLoadKind, tag) {}
338 
339 private:
340   friend class ProgramPoint;
PreLoad()341   PreLoad() {}
isKind(const ProgramPoint & location)342   static bool isKind(const ProgramPoint &location) {
343     return location.getKind() == PreLoadKind;
344   }
345 };
346 
347 class PreStore : public LocationCheck {
348 public:
349   PreStore(const Stmt *S, const LocationContext *L,
350            const ProgramPointTag *tag = 0)
LocationCheck(S,L,PreStoreKind,tag)351   : LocationCheck(S, L, PreStoreKind, tag) {}
352 
353 private:
354   friend class ProgramPoint;
PreStore()355   PreStore() {}
isKind(const ProgramPoint & location)356   static bool isKind(const ProgramPoint &location) {
357     return location.getKind() == PreStoreKind;
358   }
359 };
360 
361 class PostLoad : public PostStmt {
362 public:
363   PostLoad(const Stmt *S, const LocationContext *L,
364            const ProgramPointTag *tag = 0)
PostStmt(S,PostLoadKind,L,tag)365     : PostStmt(S, PostLoadKind, L, tag) {}
366 
367 private:
368   friend class ProgramPoint;
PostLoad()369   PostLoad() {}
isKind(const ProgramPoint & Location)370   static bool isKind(const ProgramPoint &Location) {
371     return Location.getKind() == PostLoadKind;
372   }
373 };
374 
375 /// \brief Represents a program point after a store evaluation.
376 class PostStore : public PostStmt {
377 public:
378   /// Construct the post store point.
379   /// \param Loc can be used to store the information about the location
380   /// used in the form it was uttered in the code.
381   PostStore(const Stmt *S, const LocationContext *L, const void *Loc,
382             const ProgramPointTag *tag = 0)
PostStmt(S,PostStoreKind,L,tag)383     : PostStmt(S, PostStoreKind, L, tag) {
384     assert(getData2() == 0);
385     setData2(Loc);
386   }
387 
388   /// \brief Returns the information about the location used in the store,
389   /// how it was uttered in the code.
getLocationValue()390   const void *getLocationValue() const {
391     return getData2();
392   }
393 
394 private:
395   friend class ProgramPoint;
PostStore()396   PostStore() {}
isKind(const ProgramPoint & Location)397   static bool isKind(const ProgramPoint &Location) {
398     return Location.getKind() == PostStoreKind;
399   }
400 };
401 
402 class PostLValue : public PostStmt {
403 public:
404   PostLValue(const Stmt *S, const LocationContext *L,
405              const ProgramPointTag *tag = 0)
PostStmt(S,PostLValueKind,L,tag)406     : PostStmt(S, PostLValueKind, L, tag) {}
407 
408 private:
409   friend class ProgramPoint;
PostLValue()410   PostLValue() {}
isKind(const ProgramPoint & Location)411   static bool isKind(const ProgramPoint &Location) {
412     return Location.getKind() == PostLValueKind;
413   }
414 };
415 
416 /// Represents a point after we ran remove dead bindings BEFORE
417 /// processing the given statement.
418 class PreStmtPurgeDeadSymbols : public StmtPoint {
419 public:
420   PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
421                        const ProgramPointTag *tag = 0)
422     : StmtPoint(S, 0, PreStmtPurgeDeadSymbolsKind, L, tag) { }
423 
424 private:
425   friend class ProgramPoint;
PreStmtPurgeDeadSymbols()426   PreStmtPurgeDeadSymbols() {}
isKind(const ProgramPoint & Location)427   static bool isKind(const ProgramPoint &Location) {
428     return Location.getKind() == PreStmtPurgeDeadSymbolsKind;
429   }
430 };
431 
432 /// Represents a point after we ran remove dead bindings AFTER
433 /// processing the  given statement.
434 class PostStmtPurgeDeadSymbols : public StmtPoint {
435 public:
436   PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
437                        const ProgramPointTag *tag = 0)
438     : StmtPoint(S, 0, PostStmtPurgeDeadSymbolsKind, L, tag) { }
439 
440 private:
441   friend class ProgramPoint;
PostStmtPurgeDeadSymbols()442   PostStmtPurgeDeadSymbols() {}
isKind(const ProgramPoint & Location)443   static bool isKind(const ProgramPoint &Location) {
444     return Location.getKind() == PostStmtPurgeDeadSymbolsKind;
445   }
446 };
447 
448 class BlockEdge : public ProgramPoint {
449 public:
BlockEdge(const CFGBlock * B1,const CFGBlock * B2,const LocationContext * L)450   BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
451     : ProgramPoint(B1, B2, BlockEdgeKind, L) {
452     assert(B1 && "BlockEdge: source block must be non-null");
453     assert(B2 && "BlockEdge: destination block must be non-null");
454   }
455 
getSrc()456   const CFGBlock *getSrc() const {
457     return static_cast<const CFGBlock*>(getData1());
458   }
459 
getDst()460   const CFGBlock *getDst() const {
461     return static_cast<const CFGBlock*>(getData2());
462   }
463 
464 private:
465   friend class ProgramPoint;
BlockEdge()466   BlockEdge() {}
isKind(const ProgramPoint & Location)467   static bool isKind(const ProgramPoint &Location) {
468     return Location.getKind() == BlockEdgeKind;
469   }
470 };
471 
472 class PostInitializer : public ProgramPoint {
473 public:
PostInitializer(const CXXCtorInitializer * I,const LocationContext * L)474   PostInitializer(const CXXCtorInitializer *I,
475                   const LocationContext *L)
476     : ProgramPoint(I, PostInitializerKind, L) {}
477 
478 private:
479   friend class ProgramPoint;
PostInitializer()480   PostInitializer() {}
isKind(const ProgramPoint & Location)481   static bool isKind(const ProgramPoint &Location) {
482     return Location.getKind() == PostInitializerKind;
483   }
484 };
485 
486 /// Represents an implicit call event.
487 ///
488 /// The nearest statement is provided for diagnostic purposes.
489 class ImplicitCallPoint : public ProgramPoint {
490 public:
ImplicitCallPoint(const Decl * D,SourceLocation Loc,Kind K,const LocationContext * L,const ProgramPointTag * Tag)491   ImplicitCallPoint(const Decl *D, SourceLocation Loc, Kind K,
492                     const LocationContext *L, const ProgramPointTag *Tag)
493     : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag) {}
494 
getDecl()495   const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); }
getLocation()496   SourceLocation getLocation() const {
497     return SourceLocation::getFromPtrEncoding(getData1());
498   }
499 
500 protected:
ImplicitCallPoint()501   ImplicitCallPoint() {}
502 private:
503   friend class ProgramPoint;
isKind(const ProgramPoint & Location)504   static bool isKind(const ProgramPoint &Location) {
505     return Location.getKind() >= MinImplicitCallKind &&
506            Location.getKind() <= MaxImplicitCallKind;
507   }
508 };
509 
510 /// Represents a program point just before an implicit call event.
511 ///
512 /// Explicit calls will appear as PreStmt program points.
513 class PreImplicitCall : public ImplicitCallPoint {
514 public:
515   PreImplicitCall(const Decl *D, SourceLocation Loc,
516                   const LocationContext *L, const ProgramPointTag *Tag = 0)
ImplicitCallPoint(D,Loc,PreImplicitCallKind,L,Tag)517     : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {}
518 
519 private:
520   friend class ProgramPoint;
PreImplicitCall()521   PreImplicitCall() {}
isKind(const ProgramPoint & Location)522   static bool isKind(const ProgramPoint &Location) {
523     return Location.getKind() == PreImplicitCallKind;
524   }
525 };
526 
527 /// Represents a program point just after an implicit call event.
528 ///
529 /// Explicit calls will appear as PostStmt program points.
530 class PostImplicitCall : public ImplicitCallPoint {
531 public:
532   PostImplicitCall(const Decl *D, SourceLocation Loc,
533                    const LocationContext *L, const ProgramPointTag *Tag = 0)
ImplicitCallPoint(D,Loc,PostImplicitCallKind,L,Tag)534     : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {}
535 
536 private:
537   friend class ProgramPoint;
PostImplicitCall()538   PostImplicitCall() {}
isKind(const ProgramPoint & Location)539   static bool isKind(const ProgramPoint &Location) {
540     return Location.getKind() == PostImplicitCallKind;
541   }
542 };
543 
544 /// Represents a point when we begin processing an inlined call.
545 /// CallEnter uses the caller's location context.
546 class CallEnter : public ProgramPoint {
547 public:
CallEnter(const Stmt * stmt,const StackFrameContext * calleeCtx,const LocationContext * callerCtx)548   CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
549             const LocationContext *callerCtx)
550     : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {}
551 
getCallExpr()552   const Stmt *getCallExpr() const {
553     return static_cast<const Stmt *>(getData1());
554   }
555 
getCalleeContext()556   const StackFrameContext *getCalleeContext() const {
557     return static_cast<const StackFrameContext *>(getData2());
558   }
559 
560 private:
561   friend class ProgramPoint;
CallEnter()562   CallEnter() {}
isKind(const ProgramPoint & Location)563   static bool isKind(const ProgramPoint &Location) {
564     return Location.getKind() == CallEnterKind;
565   }
566 };
567 
568 /// Represents a point when we start the call exit sequence (for inlined call).
569 ///
570 /// The call exit is simulated with a sequence of nodes, which occur between
571 /// CallExitBegin and CallExitEnd. The following operations occur between the
572 /// two program points:
573 /// - CallExitBegin
574 /// - Bind the return value
575 /// - Run Remove dead bindings (to clean up the dead symbols from the callee).
576 /// - CallExitEnd
577 class CallExitBegin : public ProgramPoint {
578 public:
579   // CallExitBegin uses the callee's location context.
CallExitBegin(const StackFrameContext * L)580   CallExitBegin(const StackFrameContext *L)
581     : ProgramPoint(0, CallExitBeginKind, L, 0) {}
582 
583 private:
584   friend class ProgramPoint;
CallExitBegin()585   CallExitBegin() {}
isKind(const ProgramPoint & Location)586   static bool isKind(const ProgramPoint &Location) {
587     return Location.getKind() == CallExitBeginKind;
588   }
589 };
590 
591 /// Represents a point when we finish the call exit sequence (for inlined call).
592 /// \sa CallExitBegin
593 class CallExitEnd : public ProgramPoint {
594 public:
595   // CallExitEnd uses the caller's location context.
CallExitEnd(const StackFrameContext * CalleeCtx,const LocationContext * CallerCtx)596   CallExitEnd(const StackFrameContext *CalleeCtx,
597               const LocationContext *CallerCtx)
598     : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, 0) {}
599 
getCalleeContext()600   const StackFrameContext *getCalleeContext() const {
601     return static_cast<const StackFrameContext *>(getData1());
602   }
603 
604 private:
605   friend class ProgramPoint;
CallExitEnd()606   CallExitEnd() {}
isKind(const ProgramPoint & Location)607   static bool isKind(const ProgramPoint &Location) {
608     return Location.getKind() == CallExitEndKind;
609   }
610 };
611 
612 /// This is a meta program point, which should be skipped by all the diagnostic
613 /// reasoning etc.
614 class EpsilonPoint : public ProgramPoint {
615 public:
616   EpsilonPoint(const LocationContext *L, const void *Data1,
617                const void *Data2 = 0, const ProgramPointTag *tag = 0)
ProgramPoint(Data1,Data2,EpsilonKind,L,tag)618     : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {}
619 
getData()620   const void *getData() const { return getData1(); }
621 
622 private:
623   friend class ProgramPoint;
EpsilonPoint()624   EpsilonPoint() {}
isKind(const ProgramPoint & Location)625   static bool isKind(const ProgramPoint &Location) {
626     return Location.getKind() == EpsilonKind;
627   }
628 };
629 
630 /// ProgramPoints can be "tagged" as representing points specific to a given
631 /// analysis entity.  Tags are abstract annotations, with an associated
632 /// description and potentially other information.
633 class ProgramPointTag {
634 public:
TagKind(tagKind)635   ProgramPointTag(void *tagKind = 0) : TagKind(tagKind) {}
636   virtual ~ProgramPointTag();
637   virtual StringRef getTagDescription() const = 0;
638 
639 protected:
640   /// Used to implement 'isKind' in subclasses.
getTagKind()641   const void *getTagKind() { return TagKind; }
642 
643 private:
644   const void *TagKind;
645 };
646 
647 class SimpleProgramPointTag : public ProgramPointTag {
648   std::string desc;
649 public:
650   SimpleProgramPointTag(StringRef description);
651   StringRef getTagDescription() const;
652 };
653 
654 } // end namespace clang
655 
656 
657 namespace llvm { // Traits specialization for DenseMap
658 
659 template <> struct DenseMapInfo<clang::ProgramPoint> {
660 
661 static inline clang::ProgramPoint getEmptyKey() {
662   uintptr_t x =
663    reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
664   return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
665 }
666 
667 static inline clang::ProgramPoint getTombstoneKey() {
668   uintptr_t x =
669    reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
670   return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
671 }
672 
673 static unsigned getHashValue(const clang::ProgramPoint &Loc) {
674   return Loc.getHashValue();
675 }
676 
677 static bool isEqual(const clang::ProgramPoint &L,
678                     const clang::ProgramPoint &R) {
679   return L == R;
680 }
681 
682 };
683 
684 template <>
685 struct isPodLike<clang::ProgramPoint> { static const bool value = true; };
686 
687 } // end namespace llvm
688 
689 #endif
690