ProgramPoint.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. //==- ProgramPoint.cpp - Program Points for Path-Sensitive Analysis -*- C++ -*-/
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file defines the interface ProgramPoint, which identifies a
  10. // distinct location in a function.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/Analysis/ProgramPoint.h"
  14. using namespace clang;
  15. ProgramPointTag::~ProgramPointTag() {}
  16. ProgramPoint ProgramPoint::getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
  17. const LocationContext *LC,
  18. const ProgramPointTag *tag){
  19. switch (K) {
  20. default:
  21. llvm_unreachable("Unhandled ProgramPoint kind");
  22. case ProgramPoint::PreStmtKind:
  23. return PreStmt(S, LC, tag);
  24. case ProgramPoint::PostStmtKind:
  25. return PostStmt(S, LC, tag);
  26. case ProgramPoint::PreLoadKind:
  27. return PreLoad(S, LC, tag);
  28. case ProgramPoint::PostLoadKind:
  29. return PostLoad(S, LC, tag);
  30. case ProgramPoint::PreStoreKind:
  31. return PreStore(S, LC, tag);
  32. case ProgramPoint::PostLValueKind:
  33. return PostLValue(S, LC, tag);
  34. case ProgramPoint::PostStmtPurgeDeadSymbolsKind:
  35. return PostStmtPurgeDeadSymbols(S, LC, tag);
  36. case ProgramPoint::PreStmtPurgeDeadSymbolsKind:
  37. return PreStmtPurgeDeadSymbols(S, LC, tag);
  38. }
  39. }
  40. LLVM_DUMP_METHOD void ProgramPoint::dump() const {
  41. return printJson(llvm::errs());
  42. }
  43. static void printLocJson(raw_ostream &Out, SourceLocation Loc,
  44. const SourceManager &SM) {
  45. Out << "\"location\": ";
  46. if (!Loc.isFileID()) {
  47. Out << "null";
  48. return;
  49. }
  50. Out << "{ \"line\": " << SM.getExpansionLineNumber(Loc)
  51. << ", \"column\": " << SM.getExpansionColumnNumber(Loc) << " }";
  52. }
  53. void ProgramPoint::printJson(llvm::raw_ostream &Out, const char *NL) const {
  54. const ASTContext &Context =
  55. getLocationContext()->getAnalysisDeclContext()->getASTContext();
  56. const SourceManager &SM = Context.getSourceManager();
  57. const PrintingPolicy &PP = Context.getPrintingPolicy();
  58. const bool AddQuotes = true;
  59. Out << "\"kind\": \"";
  60. switch (getKind()) {
  61. case ProgramPoint::BlockEntranceKind:
  62. Out << "BlockEntrance\""
  63. << ", \"block_id\": "
  64. << castAs<BlockEntrance>().getBlock()->getBlockID();
  65. break;
  66. case ProgramPoint::FunctionExitKind: {
  67. auto FEP = getAs<FunctionExitPoint>();
  68. Out << "FunctionExit\""
  69. << ", \"block_id\": " << FEP->getBlock()->getBlockID()
  70. << ", \"stmt_id\": ";
  71. if (const ReturnStmt *RS = FEP->getStmt()) {
  72. Out << RS->getID(Context) << ", \"stmt\": ";
  73. RS->printJson(Out, nullptr, PP, AddQuotes);
  74. } else {
  75. Out << "null, \"stmt\": null";
  76. }
  77. break;
  78. }
  79. case ProgramPoint::BlockExitKind:
  80. llvm_unreachable("BlockExitKind");
  81. break;
  82. case ProgramPoint::CallEnterKind:
  83. Out << "CallEnter\"";
  84. break;
  85. case ProgramPoint::CallExitBeginKind:
  86. Out << "CallExitBegin\"";
  87. break;
  88. case ProgramPoint::CallExitEndKind:
  89. Out << "CallExitEnd\"";
  90. break;
  91. case ProgramPoint::PostStmtPurgeDeadSymbolsKind:
  92. Out << "PostStmtPurgeDeadSymbols\"";
  93. break;
  94. case ProgramPoint::PreStmtPurgeDeadSymbolsKind:
  95. Out << "PreStmtPurgeDeadSymbols\"";
  96. break;
  97. case ProgramPoint::EpsilonKind:
  98. Out << "EpsilonPoint\"";
  99. break;
  100. case ProgramPoint::LoopExitKind:
  101. Out << "LoopExit\", \"stmt\": \""
  102. << castAs<LoopExit>().getLoopStmt()->getStmtClassName() << '\"';
  103. break;
  104. case ProgramPoint::PreImplicitCallKind: {
  105. ImplicitCallPoint PC = castAs<ImplicitCallPoint>();
  106. Out << "PreCall\", \"stmt\": \"";
  107. PC.getDecl()->print(Out, Context.getLangOpts());
  108. Out << "\", ";
  109. printLocJson(Out, PC.getLocation(), SM);
  110. break;
  111. }
  112. case ProgramPoint::PostImplicitCallKind: {
  113. ImplicitCallPoint PC = castAs<ImplicitCallPoint>();
  114. Out << "PostCall\", \"stmt\": \"";
  115. PC.getDecl()->print(Out, Context.getLangOpts());
  116. Out << "\", ";
  117. printLocJson(Out, PC.getLocation(), SM);
  118. break;
  119. }
  120. case ProgramPoint::PostInitializerKind: {
  121. Out << "PostInitializer\", ";
  122. const CXXCtorInitializer *Init = castAs<PostInitializer>().getInitializer();
  123. if (const FieldDecl *FD = Init->getAnyMember()) {
  124. Out << "\"field_decl\": \"" << *FD << '\"';
  125. } else {
  126. Out << "\"type\": \"";
  127. QualType Ty = Init->getTypeSourceInfo()->getType();
  128. Ty = Ty.getLocalUnqualifiedType();
  129. Ty.print(Out, Context.getLangOpts());
  130. Out << '\"';
  131. }
  132. break;
  133. }
  134. case ProgramPoint::BlockEdgeKind: {
  135. const BlockEdge &E = castAs<BlockEdge>();
  136. const Stmt *T = E.getSrc()->getTerminatorStmt();
  137. Out << "Edge\", \"src_id\": " << E.getSrc()->getBlockID()
  138. << ", \"dst_id\": " << E.getDst()->getBlockID()
  139. << ", \"terminator\": " << (!T ? "null, \"term_kind\": null" : "\"");
  140. if (!T)
  141. break;
  142. E.getSrc()->printTerminator(Out, Context.getLangOpts());
  143. Out << "\", ";
  144. printLocJson(Out, T->getBeginLoc(), SM);
  145. Out << ", \"term_kind\": \"";
  146. if (isa<SwitchStmt>(T)) {
  147. Out << "SwitchStmt\", \"case\": ";
  148. if (const Stmt *Label = E.getDst()->getLabel()) {
  149. if (const auto *C = dyn_cast<CaseStmt>(Label)) {
  150. Out << "{ \"lhs\": ";
  151. if (const Stmt *LHS = C->getLHS()) {
  152. LHS->printJson(Out, nullptr, PP, AddQuotes);
  153. } else {
  154. Out << "null";
  155. }
  156. Out << ", \"rhs\": ";
  157. if (const Stmt *RHS = C->getRHS()) {
  158. RHS->printJson(Out, nullptr, PP, AddQuotes);
  159. } else {
  160. Out << "null";
  161. }
  162. Out << " }";
  163. } else {
  164. assert(isa<DefaultStmt>(Label));
  165. Out << "\"default\"";
  166. }
  167. } else {
  168. Out << "\"implicit default\"";
  169. }
  170. } else if (isa<IndirectGotoStmt>(T)) {
  171. // FIXME: More info.
  172. Out << "IndirectGotoStmt\"";
  173. } else {
  174. Out << "Condition\", \"value\": "
  175. << (*E.getSrc()->succ_begin() == E.getDst() ? "true" : "false");
  176. }
  177. break;
  178. }
  179. default: {
  180. const Stmt *S = castAs<StmtPoint>().getStmt();
  181. assert(S != nullptr && "Expecting non-null Stmt");
  182. Out << "Statement\", \"stmt_kind\": \"" << S->getStmtClassName()
  183. << "\", \"stmt_id\": " << S->getID(Context)
  184. << ", \"pointer\": \"" << (const void *)S << "\", \"pretty\": ";
  185. S->printJson(Out, nullptr, PP, AddQuotes);
  186. Out << ", ";
  187. printLocJson(Out, S->getBeginLoc(), SM);
  188. Out << ", \"stmt_point_kind\": ";
  189. if (getAs<PreStmt>())
  190. Out << "\"PreStmt\"";
  191. else if (getAs<PostLoad>())
  192. Out << "\"PostLoad\"";
  193. else if (getAs<PostStore>())
  194. Out << "\"PostStore\"";
  195. else if (getAs<PostLValue>())
  196. Out << "\"PostLValue\"";
  197. else if (getAs<PostAllocatorCall>())
  198. Out << "\"PostAllocatorCall\"";
  199. else
  200. Out << "null";
  201. break;
  202. }
  203. }
  204. }
  205. SimpleProgramPointTag::SimpleProgramPointTag(StringRef MsgProvider,
  206. StringRef Msg)
  207. : Desc((MsgProvider + " : " + Msg).str()) {}
  208. StringRef SimpleProgramPointTag::getTagDescription() const {
  209. return Desc;
  210. }