ProgramPoint.h 23 KB

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