File indexing completed on 2026-05-10 08:36:26
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H
0015 #define LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H
0016
0017 #include "clang/Analysis/AnalysisDeclContext.h"
0018 #include "clang/Analysis/CFG.h"
0019 #include "llvm/ADT/DenseMap.h"
0020 #include "llvm/ADT/FoldingSet.h"
0021 #include "llvm/ADT/PointerIntPair.h"
0022 #include "llvm/ADT/StringRef.h"
0023 #include "llvm/Support/Casting.h"
0024 #include "llvm/Support/DataTypes.h"
0025 #include <cassert>
0026 #include <optional>
0027 #include <string>
0028 #include <utility>
0029
0030 namespace clang {
0031
0032 class AnalysisDeclContext;
0033 class LocationContext;
0034
0035
0036
0037
0038 class ProgramPointTag {
0039 public:
0040 ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {}
0041 virtual ~ProgramPointTag();
0042 virtual StringRef getTagDescription() const = 0;
0043
0044
0045 const void *getTagKind() const { return TagKind; }
0046
0047 private:
0048 const void *const TagKind;
0049 };
0050
0051 class SimpleProgramPointTag : public ProgramPointTag {
0052 std::string Desc;
0053 public:
0054 SimpleProgramPointTag(StringRef MsgProvider, StringRef Msg);
0055 StringRef getTagDescription() const override;
0056 };
0057
0058 class ProgramPoint {
0059 public:
0060 enum Kind { BlockEdgeKind,
0061 BlockEntranceKind,
0062 BlockExitKind,
0063 PreStmtKind,
0064 PreStmtPurgeDeadSymbolsKind,
0065 PostStmtPurgeDeadSymbolsKind,
0066 PostStmtKind,
0067 PreLoadKind,
0068 PostLoadKind,
0069 PreStoreKind,
0070 PostStoreKind,
0071 PostConditionKind,
0072 PostLValueKind,
0073 PostAllocatorCallKind,
0074 MinPostStmtKind = PostStmtKind,
0075 MaxPostStmtKind = PostAllocatorCallKind,
0076 PostInitializerKind,
0077 CallEnterKind,
0078 CallExitBeginKind,
0079 CallExitEndKind,
0080 FunctionExitKind,
0081 PreImplicitCallKind,
0082 PostImplicitCallKind,
0083 MinImplicitCallKind = PreImplicitCallKind,
0084 MaxImplicitCallKind = PostImplicitCallKind,
0085 LoopExitKind,
0086 EpsilonKind};
0087
0088 private:
0089 const void *Data1;
0090 llvm::PointerIntPair<const void *, 2, unsigned> Data2;
0091
0092
0093
0094 llvm::PointerIntPair<const LocationContext *, 2, unsigned> L;
0095
0096 llvm::PointerIntPair<const ProgramPointTag *, 2, unsigned> Tag;
0097
0098 CFGBlock::ConstCFGElementRef ElemRef = {nullptr, 0};
0099
0100 protected:
0101 ProgramPoint() = default;
0102 ProgramPoint(const void *P, Kind k, const LocationContext *l,
0103 const ProgramPointTag *tag = nullptr,
0104 CFGBlock::ConstCFGElementRef ElemRef = {nullptr, 0})
0105 : Data1(P), Data2(nullptr, (((unsigned)k) >> 0) & 0x3),
0106 L(l, (((unsigned)k) >> 2) & 0x3), Tag(tag, (((unsigned)k) >> 4) & 0x3),
0107 ElemRef(ElemRef) {
0108 assert(getKind() == k);
0109 assert(getLocationContext() == l);
0110 assert(getData1() == P);
0111 }
0112
0113 ProgramPoint(const void *P1, const void *P2, Kind k, const LocationContext *l,
0114 const ProgramPointTag *tag = nullptr,
0115 CFGBlock::ConstCFGElementRef ElemRef = {nullptr, 0})
0116 : Data1(P1), Data2(P2, (((unsigned)k) >> 0) & 0x3),
0117 L(l, (((unsigned)k) >> 2) & 0x3), Tag(tag, (((unsigned)k) >> 4) & 0x3),
0118 ElemRef(ElemRef) {}
0119
0120 protected:
0121 const void *getData1() const { return Data1; }
0122 const void *getData2() const { return Data2.getPointer(); }
0123 void setData2(const void *d) { Data2.setPointer(d); }
0124 CFGBlock::ConstCFGElementRef getElementRef() const { return ElemRef; }
0125
0126 public:
0127
0128
0129 ProgramPoint withTag(const ProgramPointTag *tag) const {
0130 return ProgramPoint(getData1(), getData2(), getKind(),
0131 getLocationContext(), tag);
0132 }
0133
0134
0135
0136 template<typename T>
0137 T castAs() const {
0138 assert(T::isKind(*this));
0139 T t;
0140 ProgramPoint& PP = t;
0141 PP = *this;
0142 return t;
0143 }
0144
0145
0146
0147 template <typename T> std::optional<T> getAs() const {
0148 if (!T::isKind(*this))
0149 return std::nullopt;
0150 T t;
0151 ProgramPoint& PP = t;
0152 PP = *this;
0153 return t;
0154 }
0155
0156 Kind getKind() const {
0157 unsigned x = Tag.getInt();
0158 x <<= 2;
0159 x |= L.getInt();
0160 x <<= 2;
0161 x |= Data2.getInt();
0162 return (Kind) x;
0163 }
0164
0165
0166
0167 bool isPurgeKind() {
0168 Kind K = getKind();
0169 return (K == PostStmtPurgeDeadSymbolsKind ||
0170 K == PreStmtPurgeDeadSymbolsKind);
0171 }
0172
0173 const ProgramPointTag *getTag() const { return Tag.getPointer(); }
0174
0175 const LocationContext *getLocationContext() const {
0176 return L.getPointer();
0177 }
0178
0179 const StackFrameContext *getStackFrame() const {
0180 return getLocationContext()->getStackFrame();
0181 }
0182
0183
0184 unsigned getHashValue() const {
0185 llvm::FoldingSetNodeID ID;
0186 Profile(ID);
0187 return ID.ComputeHash();
0188 }
0189
0190 bool operator==(const ProgramPoint & RHS) const {
0191 return Data1 == RHS.Data1 && Data2 == RHS.Data2 && L == RHS.L &&
0192 Tag == RHS.Tag && ElemRef == RHS.ElemRef;
0193 }
0194
0195 bool operator!=(const ProgramPoint &RHS) const {
0196 return Data1 != RHS.Data1 || Data2 != RHS.Data2 || L != RHS.L ||
0197 Tag != RHS.Tag || ElemRef != RHS.ElemRef;
0198 }
0199
0200 void Profile(llvm::FoldingSetNodeID& ID) const {
0201 ID.AddInteger((unsigned) getKind());
0202 ID.AddPointer(getData1());
0203 ID.AddPointer(getData2());
0204 ID.AddPointer(getLocationContext());
0205 ID.AddPointer(getTag());
0206 ID.AddPointer(ElemRef.getParent());
0207 ID.AddInteger(ElemRef.getIndexInBlock());
0208 }
0209
0210 void printJson(llvm::raw_ostream &Out, const char *NL = "\n") const;
0211
0212 LLVM_DUMP_METHOD void dump() const;
0213
0214 static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
0215 const LocationContext *LC,
0216 const ProgramPointTag *tag);
0217 };
0218
0219 class BlockEntrance : public ProgramPoint {
0220 public:
0221 BlockEntrance(const CFGBlock *B, const LocationContext *L,
0222 const ProgramPointTag *tag = nullptr)
0223 : ProgramPoint(B, BlockEntranceKind, L, tag) {
0224 assert(B && "BlockEntrance requires non-null block");
0225 }
0226
0227 const CFGBlock *getBlock() const {
0228 return reinterpret_cast<const CFGBlock*>(getData1());
0229 }
0230
0231 std::optional<CFGElement> getFirstElement() const {
0232 const CFGBlock *B = getBlock();
0233 return B->empty() ? std::optional<CFGElement>() : B->front();
0234 }
0235
0236 private:
0237 friend class ProgramPoint;
0238 BlockEntrance() = default;
0239 static bool isKind(const ProgramPoint &Location) {
0240 return Location.getKind() == BlockEntranceKind;
0241 }
0242 };
0243
0244 class BlockExit : public ProgramPoint {
0245 public:
0246 BlockExit(const CFGBlock *B, const LocationContext *L)
0247 : ProgramPoint(B, BlockExitKind, L) {}
0248
0249 const CFGBlock *getBlock() const {
0250 return reinterpret_cast<const CFGBlock*>(getData1());
0251 }
0252
0253 const Stmt *getTerminator() const {
0254 return getBlock()->getTerminatorStmt();
0255 }
0256
0257 private:
0258 friend class ProgramPoint;
0259 BlockExit() = default;
0260 static bool isKind(const ProgramPoint &Location) {
0261 return Location.getKind() == BlockExitKind;
0262 }
0263 };
0264
0265
0266 class StmtPoint : public ProgramPoint {
0267 public:
0268 StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
0269 const ProgramPointTag *tag)
0270 : ProgramPoint(S, p2, k, L, tag) {
0271 assert(S);
0272 }
0273
0274 const Stmt *getStmt() const { return (const Stmt*) getData1(); }
0275
0276 template <typename T>
0277 const T* getStmtAs() const { return dyn_cast<T>(getStmt()); }
0278
0279 protected:
0280 StmtPoint() = default;
0281 private:
0282 friend class ProgramPoint;
0283 static bool isKind(const ProgramPoint &Location) {
0284 unsigned k = Location.getKind();
0285 return k >= PreStmtKind && k <= MaxPostStmtKind;
0286 }
0287 };
0288
0289
0290 class PreStmt : public StmtPoint {
0291 public:
0292 PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag,
0293 const Stmt *SubStmt = nullptr)
0294 : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
0295
0296 const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
0297
0298 private:
0299 friend class ProgramPoint;
0300 PreStmt() = default;
0301 static bool isKind(const ProgramPoint &Location) {
0302 return Location.getKind() == PreStmtKind;
0303 }
0304 };
0305
0306 class PostStmt : public StmtPoint {
0307 protected:
0308 PostStmt() = default;
0309 PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
0310 const ProgramPointTag *tag = nullptr)
0311 : StmtPoint(S, data, k, L, tag) {}
0312
0313 public:
0314 explicit PostStmt(const Stmt *S, Kind k, const LocationContext *L,
0315 const ProgramPointTag *tag = nullptr)
0316 : StmtPoint(S, nullptr, k, L, tag) {}
0317
0318 explicit PostStmt(const Stmt *S, const LocationContext *L,
0319 const ProgramPointTag *tag = nullptr)
0320 : StmtPoint(S, nullptr, PostStmtKind, L, tag) {}
0321
0322 private:
0323 friend class ProgramPoint;
0324 static bool isKind(const ProgramPoint &Location) {
0325 unsigned k = Location.getKind();
0326 return k >= MinPostStmtKind && k <= MaxPostStmtKind;
0327 }
0328 };
0329
0330 class FunctionExitPoint : public ProgramPoint {
0331 public:
0332 explicit FunctionExitPoint(const ReturnStmt *S,
0333 const LocationContext *LC,
0334 const ProgramPointTag *tag = nullptr)
0335 : ProgramPoint(S, FunctionExitKind, LC, tag) {}
0336
0337 const CFGBlock *getBlock() const {
0338 return &getLocationContext()->getCFG()->getExit();
0339 }
0340
0341 const ReturnStmt *getStmt() const {
0342 return reinterpret_cast<const ReturnStmt *>(getData1());
0343 }
0344
0345 private:
0346 friend class ProgramPoint;
0347 FunctionExitPoint() = default;
0348 static bool isKind(const ProgramPoint &Location) {
0349 return Location.getKind() == FunctionExitKind;
0350 }
0351 };
0352
0353
0354 class PostCondition : public PostStmt {
0355 public:
0356 PostCondition(const Stmt *S, const LocationContext *L,
0357 const ProgramPointTag *tag = nullptr)
0358 : PostStmt(S, PostConditionKind, L, tag) {}
0359
0360 private:
0361 friend class ProgramPoint;
0362 PostCondition() = default;
0363 static bool isKind(const ProgramPoint &Location) {
0364 return Location.getKind() == PostConditionKind;
0365 }
0366 };
0367
0368 class LocationCheck : public StmtPoint {
0369 protected:
0370 LocationCheck() = default;
0371 LocationCheck(const Stmt *S, const LocationContext *L,
0372 ProgramPoint::Kind K, const ProgramPointTag *tag)
0373 : StmtPoint(S, nullptr, K, L, tag) {}
0374
0375 private:
0376 friend class ProgramPoint;
0377 static bool isKind(const ProgramPoint &location) {
0378 unsigned k = location.getKind();
0379 return k == PreLoadKind || k == PreStoreKind;
0380 }
0381 };
0382
0383 class PreLoad : public LocationCheck {
0384 public:
0385 PreLoad(const Stmt *S, const LocationContext *L,
0386 const ProgramPointTag *tag = nullptr)
0387 : LocationCheck(S, L, PreLoadKind, tag) {}
0388
0389 private:
0390 friend class ProgramPoint;
0391 PreLoad() = default;
0392 static bool isKind(const ProgramPoint &location) {
0393 return location.getKind() == PreLoadKind;
0394 }
0395 };
0396
0397 class PreStore : public LocationCheck {
0398 public:
0399 PreStore(const Stmt *S, const LocationContext *L,
0400 const ProgramPointTag *tag = nullptr)
0401 : LocationCheck(S, L, PreStoreKind, tag) {}
0402
0403 private:
0404 friend class ProgramPoint;
0405 PreStore() = default;
0406 static bool isKind(const ProgramPoint &location) {
0407 return location.getKind() == PreStoreKind;
0408 }
0409 };
0410
0411 class PostLoad : public PostStmt {
0412 public:
0413 PostLoad(const Stmt *S, const LocationContext *L,
0414 const ProgramPointTag *tag = nullptr)
0415 : PostStmt(S, PostLoadKind, L, tag) {}
0416
0417 private:
0418 friend class ProgramPoint;
0419 PostLoad() = default;
0420 static bool isKind(const ProgramPoint &Location) {
0421 return Location.getKind() == PostLoadKind;
0422 }
0423 };
0424
0425
0426 class PostStore : public PostStmt {
0427 public:
0428
0429
0430
0431 PostStore(const Stmt *S, const LocationContext *L, const void *Loc,
0432 const ProgramPointTag *tag = nullptr)
0433 : PostStmt(S, PostStoreKind, L, tag) {
0434 assert(getData2() == nullptr);
0435 setData2(Loc);
0436 }
0437
0438
0439
0440 const void *getLocationValue() const {
0441 return getData2();
0442 }
0443
0444 private:
0445 friend class ProgramPoint;
0446 PostStore() = default;
0447 static bool isKind(const ProgramPoint &Location) {
0448 return Location.getKind() == PostStoreKind;
0449 }
0450 };
0451
0452 class PostLValue : public PostStmt {
0453 public:
0454 PostLValue(const Stmt *S, const LocationContext *L,
0455 const ProgramPointTag *tag = nullptr)
0456 : PostStmt(S, PostLValueKind, L, tag) {}
0457
0458 private:
0459 friend class ProgramPoint;
0460 PostLValue() = default;
0461 static bool isKind(const ProgramPoint &Location) {
0462 return Location.getKind() == PostLValueKind;
0463 }
0464 };
0465
0466
0467
0468 class PreStmtPurgeDeadSymbols : public StmtPoint {
0469 public:
0470 PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
0471 const ProgramPointTag *tag = nullptr)
0472 : StmtPoint(S, nullptr, PreStmtPurgeDeadSymbolsKind, L, tag) { }
0473
0474 private:
0475 friend class ProgramPoint;
0476 PreStmtPurgeDeadSymbols() = default;
0477 static bool isKind(const ProgramPoint &Location) {
0478 return Location.getKind() == PreStmtPurgeDeadSymbolsKind;
0479 }
0480 };
0481
0482
0483
0484 class PostStmtPurgeDeadSymbols : public StmtPoint {
0485 public:
0486 PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
0487 const ProgramPointTag *tag = nullptr)
0488 : StmtPoint(S, nullptr, PostStmtPurgeDeadSymbolsKind, L, tag) { }
0489
0490 private:
0491 friend class ProgramPoint;
0492 PostStmtPurgeDeadSymbols() = default;
0493 static bool isKind(const ProgramPoint &Location) {
0494 return Location.getKind() == PostStmtPurgeDeadSymbolsKind;
0495 }
0496 };
0497
0498 class BlockEdge : public ProgramPoint {
0499 public:
0500 BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
0501 : ProgramPoint(B1, B2, BlockEdgeKind, L) {
0502 assert(B1 && "BlockEdge: source block must be non-null");
0503 assert(B2 && "BlockEdge: destination block must be non-null");
0504 }
0505
0506 const CFGBlock *getSrc() const {
0507 return static_cast<const CFGBlock*>(getData1());
0508 }
0509
0510 const CFGBlock *getDst() const {
0511 return static_cast<const CFGBlock*>(getData2());
0512 }
0513
0514 private:
0515 friend class ProgramPoint;
0516 BlockEdge() = default;
0517 static bool isKind(const ProgramPoint &Location) {
0518 return Location.getKind() == BlockEdgeKind;
0519 }
0520 };
0521
0522 class PostInitializer : public ProgramPoint {
0523 public:
0524
0525
0526
0527
0528
0529 PostInitializer(const CXXCtorInitializer *I,
0530 const void *Loc,
0531 const LocationContext *L)
0532 : ProgramPoint(I, Loc, PostInitializerKind, L) {}
0533
0534 const CXXCtorInitializer *getInitializer() const {
0535 return static_cast<const CXXCtorInitializer *>(getData1());
0536 }
0537
0538
0539 const void *getLocationValue() const {
0540 return getData2();
0541 }
0542
0543 private:
0544 friend class ProgramPoint;
0545 PostInitializer() = default;
0546 static bool isKind(const ProgramPoint &Location) {
0547 return Location.getKind() == PostInitializerKind;
0548 }
0549 };
0550
0551
0552
0553
0554 class ImplicitCallPoint : public ProgramPoint {
0555 public:
0556 ImplicitCallPoint(const Decl *D, SourceLocation Loc, Kind K,
0557 const LocationContext *L, const ProgramPointTag *Tag,
0558 CFGBlock::ConstCFGElementRef ElemRef)
0559 : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag, ElemRef) {}
0560
0561 const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); }
0562 SourceLocation getLocation() const {
0563 return SourceLocation::getFromPtrEncoding(getData1());
0564 }
0565
0566 protected:
0567 ImplicitCallPoint() = default;
0568 private:
0569 friend class ProgramPoint;
0570 static bool isKind(const ProgramPoint &Location) {
0571 return Location.getKind() >= MinImplicitCallKind &&
0572 Location.getKind() <= MaxImplicitCallKind;
0573 }
0574 };
0575
0576
0577
0578
0579 class PreImplicitCall : public ImplicitCallPoint {
0580 public:
0581 PreImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
0582 CFGBlock::ConstCFGElementRef ElemRef,
0583 const ProgramPointTag *Tag = nullptr)
0584 : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag, ElemRef) {}
0585
0586 private:
0587 friend class ProgramPoint;
0588 PreImplicitCall() = default;
0589 static bool isKind(const ProgramPoint &Location) {
0590 return Location.getKind() == PreImplicitCallKind;
0591 }
0592 };
0593
0594
0595
0596
0597 class PostImplicitCall : public ImplicitCallPoint {
0598 public:
0599 PostImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
0600 CFGBlock::ConstCFGElementRef ElemRef,
0601 const ProgramPointTag *Tag = nullptr)
0602 : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag, ElemRef) {}
0603
0604 private:
0605 friend class ProgramPoint;
0606 PostImplicitCall() = default;
0607 static bool isKind(const ProgramPoint &Location) {
0608 return Location.getKind() == PostImplicitCallKind;
0609 }
0610 };
0611
0612 class PostAllocatorCall : public StmtPoint {
0613 public:
0614 PostAllocatorCall(const Stmt *S, const LocationContext *L,
0615 const ProgramPointTag *Tag = nullptr)
0616 : StmtPoint(S, nullptr, PostAllocatorCallKind, L, Tag) {}
0617
0618 private:
0619 friend class ProgramPoint;
0620 PostAllocatorCall() = default;
0621 static bool isKind(const ProgramPoint &Location) {
0622 return Location.getKind() == PostAllocatorCallKind;
0623 }
0624 };
0625
0626
0627
0628 class CallEnter : public ProgramPoint {
0629 public:
0630 CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
0631 const LocationContext *callerCtx)
0632 : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, nullptr) {}
0633
0634 const Stmt *getCallExpr() const {
0635 return static_cast<const Stmt *>(getData1());
0636 }
0637
0638 const StackFrameContext *getCalleeContext() const {
0639 return static_cast<const StackFrameContext *>(getData2());
0640 }
0641
0642
0643 const CFGBlock *getEntry() const {
0644 const StackFrameContext *CalleeCtx = getCalleeContext();
0645 const CFG *CalleeCFG = CalleeCtx->getCFG();
0646 return &(CalleeCFG->getEntry());
0647 }
0648
0649 private:
0650 friend class ProgramPoint;
0651 CallEnter() = default;
0652 static bool isKind(const ProgramPoint &Location) {
0653 return Location.getKind() == CallEnterKind;
0654 }
0655 };
0656
0657
0658
0659
0660
0661
0662
0663
0664
0665
0666 class CallExitBegin : public ProgramPoint {
0667 public:
0668
0669 CallExitBegin(const StackFrameContext *L, const ReturnStmt *RS)
0670 : ProgramPoint(RS, CallExitBeginKind, L, nullptr) { }
0671
0672 const ReturnStmt *getReturnStmt() const {
0673 return static_cast<const ReturnStmt *>(getData1());
0674 }
0675
0676 private:
0677 friend class ProgramPoint;
0678 CallExitBegin() = default;
0679 static bool isKind(const ProgramPoint &Location) {
0680 return Location.getKind() == CallExitBeginKind;
0681 }
0682 };
0683
0684
0685
0686 class CallExitEnd : public ProgramPoint {
0687 public:
0688
0689 CallExitEnd(const StackFrameContext *CalleeCtx,
0690 const LocationContext *CallerCtx)
0691 : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, nullptr) {}
0692
0693 const StackFrameContext *getCalleeContext() const {
0694 return static_cast<const StackFrameContext *>(getData1());
0695 }
0696
0697 private:
0698 friend class ProgramPoint;
0699 CallExitEnd() = default;
0700 static bool isKind(const ProgramPoint &Location) {
0701 return Location.getKind() == CallExitEndKind;
0702 }
0703 };
0704
0705
0706
0707
0708
0709
0710
0711 class LoopExit : public ProgramPoint {
0712 public:
0713 LoopExit(const Stmt *LoopStmt, const LocationContext *LC)
0714 : ProgramPoint(LoopStmt, nullptr, LoopExitKind, LC) {}
0715
0716 const Stmt *getLoopStmt() const {
0717 return static_cast<const Stmt *>(getData1());
0718 }
0719
0720 private:
0721 friend class ProgramPoint;
0722 LoopExit() = default;
0723 static bool isKind(const ProgramPoint &Location) {
0724 return Location.getKind() == LoopExitKind;
0725 }
0726 };
0727
0728
0729
0730 class EpsilonPoint : public ProgramPoint {
0731 public:
0732 EpsilonPoint(const LocationContext *L, const void *Data1,
0733 const void *Data2 = nullptr,
0734 const ProgramPointTag *tag = nullptr)
0735 : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {}
0736
0737 const void *getData() const { return getData1(); }
0738
0739 private:
0740 friend class ProgramPoint;
0741 EpsilonPoint() = default;
0742 static bool isKind(const ProgramPoint &Location) {
0743 return Location.getKind() == EpsilonKind;
0744 }
0745 };
0746
0747 }
0748
0749
0750 namespace llvm {
0751
0752 template <> struct DenseMapInfo<clang::ProgramPoint> {
0753
0754 static inline clang::ProgramPoint getEmptyKey() {
0755 uintptr_t x =
0756 reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
0757 return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr);
0758 }
0759
0760 static inline clang::ProgramPoint getTombstoneKey() {
0761 uintptr_t x =
0762 reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
0763 return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr);
0764 }
0765
0766 static unsigned getHashValue(const clang::ProgramPoint &Loc) {
0767 return Loc.getHashValue();
0768 }
0769
0770 static bool isEqual(const clang::ProgramPoint &L,
0771 const clang::ProgramPoint &R) {
0772 return L == R;
0773 }
0774
0775 };
0776
0777 }
0778
0779 #endif