ProgramPoint.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. //==- ProgramPoint.cpp - Program Points for Path-Sensitive Analysis -*- C++ -*-/
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines the interface ProgramPoint, which identifies a
  11. // distinct location in a function.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "clang/Analysis/ProgramPoint.h"
  15. using namespace clang;
  16. ProgramPointTag::~ProgramPointTag() {}
  17. ProgramPoint ProgramPoint::getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
  18. const LocationContext *LC,
  19. const ProgramPointTag *tag){
  20. switch (K) {
  21. default:
  22. llvm_unreachable("Unhandled ProgramPoint kind");
  23. case ProgramPoint::PreStmtKind:
  24. return PreStmt(S, LC, tag);
  25. case ProgramPoint::PostStmtKind:
  26. return PostStmt(S, LC, tag);
  27. case ProgramPoint::PreLoadKind:
  28. return PreLoad(S, LC, tag);
  29. case ProgramPoint::PostLoadKind:
  30. return PostLoad(S, LC, tag);
  31. case ProgramPoint::PreStoreKind:
  32. return PreStore(S, LC, tag);
  33. case ProgramPoint::PostLValueKind:
  34. return PostLValue(S, LC, tag);
  35. case ProgramPoint::PostStmtPurgeDeadSymbolsKind:
  36. return PostStmtPurgeDeadSymbols(S, LC, tag);
  37. case ProgramPoint::PreStmtPurgeDeadSymbolsKind:
  38. return PreStmtPurgeDeadSymbols(S, LC, tag);
  39. }
  40. }
  41. static void printLocation(raw_ostream &Out, SourceLocation SLoc,
  42. const SourceManager &SM,
  43. StringRef CR,
  44. StringRef Postfix) {
  45. if (SLoc.isFileID()) {
  46. Out << CR << "line=" << SM.getExpansionLineNumber(SLoc)
  47. << " col=" << SM.getExpansionColumnNumber(SLoc) << Postfix;
  48. }
  49. }
  50. void ProgramPoint::print(StringRef CR, llvm::raw_ostream &Out) const {
  51. const ASTContext &Context =
  52. getLocationContext()->getAnalysisDeclContext()->getASTContext();
  53. const SourceManager &SM = Context.getSourceManager();
  54. switch (getKind()) {
  55. case ProgramPoint::BlockEntranceKind:
  56. Out << "Block Entrance: B"
  57. << castAs<BlockEntrance>().getBlock()->getBlockID();
  58. break;
  59. case ProgramPoint::FunctionExitKind: {
  60. auto FEP = getAs<FunctionExitPoint>();
  61. Out << "Function Exit: B" << FEP->getBlock()->getBlockID();
  62. if (const ReturnStmt *RS = FEP->getStmt()) {
  63. Out << CR << " Return: S" << RS->getID(Context) << CR;
  64. RS->printPretty(Out, /*helper=*/nullptr, Context.getPrintingPolicy(),
  65. /*Indentation=*/2, /*NewlineSymbol=*/CR);
  66. }
  67. break;
  68. }
  69. case ProgramPoint::BlockExitKind:
  70. assert(false);
  71. break;
  72. case ProgramPoint::CallEnterKind:
  73. Out << "CallEnter";
  74. break;
  75. case ProgramPoint::CallExitBeginKind:
  76. Out << "CallExitBegin";
  77. break;
  78. case ProgramPoint::CallExitEndKind:
  79. Out << "CallExitEnd";
  80. break;
  81. case ProgramPoint::PostStmtPurgeDeadSymbolsKind:
  82. Out << "PostStmtPurgeDeadSymbols";
  83. break;
  84. case ProgramPoint::PreStmtPurgeDeadSymbolsKind:
  85. Out << "PreStmtPurgeDeadSymbols";
  86. break;
  87. case ProgramPoint::EpsilonKind:
  88. Out << "Epsilon Point";
  89. break;
  90. case ProgramPoint::LoopExitKind: {
  91. LoopExit LE = castAs<LoopExit>();
  92. Out << "LoopExit: " << LE.getLoopStmt()->getStmtClassName();
  93. break;
  94. }
  95. case ProgramPoint::PreImplicitCallKind: {
  96. ImplicitCallPoint PC = castAs<ImplicitCallPoint>();
  97. Out << "PreCall: ";
  98. PC.getDecl()->print(Out, Context.getLangOpts());
  99. printLocation(Out, PC.getLocation(), SM, CR, /*Postfix=*/CR);
  100. break;
  101. }
  102. case ProgramPoint::PostImplicitCallKind: {
  103. ImplicitCallPoint PC = castAs<ImplicitCallPoint>();
  104. Out << "PostCall: ";
  105. PC.getDecl()->print(Out, Context.getLangOpts());
  106. printLocation(Out, PC.getLocation(), SM, CR, /*Postfix=*/CR);
  107. break;
  108. }
  109. case ProgramPoint::PostInitializerKind: {
  110. Out << "PostInitializer: ";
  111. const CXXCtorInitializer *Init = castAs<PostInitializer>().getInitializer();
  112. if (const FieldDecl *FD = Init->getAnyMember())
  113. Out << *FD;
  114. else {
  115. QualType Ty = Init->getTypeSourceInfo()->getType();
  116. Ty = Ty.getLocalUnqualifiedType();
  117. Ty.print(Out, Context.getLangOpts());
  118. }
  119. break;
  120. }
  121. case ProgramPoint::BlockEdgeKind: {
  122. const BlockEdge &E = castAs<BlockEdge>();
  123. Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
  124. << E.getDst()->getBlockID() << ')';
  125. if (const Stmt *T = E.getSrc()->getTerminator()) {
  126. SourceLocation SLoc = T->getBeginLoc();
  127. Out << "\\|Terminator: ";
  128. E.getSrc()->printTerminator(Out, Context.getLangOpts());
  129. printLocation(Out, SLoc, SM, CR, /*Postfix=*/"");
  130. if (isa<SwitchStmt>(T)) {
  131. const Stmt *Label = E.getDst()->getLabel();
  132. if (Label) {
  133. if (const auto *C = dyn_cast<CaseStmt>(Label)) {
  134. Out << CR << "case ";
  135. if (C->getLHS())
  136. C->getLHS()->printPretty(
  137. Out, nullptr, Context.getPrintingPolicy(),
  138. /*Indentation=*/0, /*NewlineSymbol=*/CR);
  139. if (const Stmt *RHS = C->getRHS()) {
  140. Out << " .. ";
  141. RHS->printPretty(Out, nullptr, Context.getPrintingPolicy(),
  142. /*Indetation=*/0, /*NewlineSymbol=*/CR);
  143. }
  144. Out << ":";
  145. } else {
  146. assert(isa<DefaultStmt>(Label));
  147. Out << CR << "default:";
  148. }
  149. } else
  150. Out << CR << "(implicit) default:";
  151. } else if (isa<IndirectGotoStmt>(T)) {
  152. // FIXME
  153. } else {
  154. Out << CR << "Condition: ";
  155. if (*E.getSrc()->succ_begin() == E.getDst())
  156. Out << "true";
  157. else
  158. Out << "false";
  159. }
  160. Out << CR;
  161. }
  162. break;
  163. }
  164. default: {
  165. const Stmt *S = castAs<StmtPoint>().getStmt();
  166. assert(S != nullptr && "Expecting non-null Stmt");
  167. Out << S->getStmtClassName() << " S" << S->getID(Context) << " <"
  168. << (const void *)S << "> ";
  169. S->printPretty(Out, /*helper=*/nullptr, Context.getPrintingPolicy(),
  170. /*Indentation=*/2, /*NewlineSymbol=*/CR);
  171. printLocation(Out, S->getBeginLoc(), SM, CR, /*Postfix=*/"");
  172. if (getAs<PreStmt>())
  173. Out << CR << "PreStmt" << CR;
  174. else if (getAs<PostLoad>())
  175. Out << CR << "PostLoad" << CR;
  176. else if (getAs<PostStore>())
  177. Out << CR << "PostStore" << CR;
  178. else if (getAs<PostLValue>())
  179. Out << CR << "PostLValue" << CR;
  180. else if (getAs<PostAllocatorCall>())
  181. Out << CR << "PostAllocatorCall" << CR;
  182. break;
  183. }
  184. }
  185. }
  186. SimpleProgramPointTag::SimpleProgramPointTag(StringRef MsgProvider,
  187. StringRef Msg)
  188. : Desc((MsgProvider + " : " + Msg).str()) {}
  189. StringRef SimpleProgramPointTag::getTagDescription() const {
  190. return Desc;
  191. }