ProgramPoint.h 23 KB

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