ProgramPoint.cpp 7.6 KB

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