TraversalChecker.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. //== TraversalChecker.cpp -------------------------------------- -*- 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. // These checkers print various aspects of the ExprEngine's traversal of the CFG
  11. // as it builds the ExplodedGraph.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "ClangSACheckers.h"
  15. #include "clang/AST/ParentMap.h"
  16. #include "clang/AST/StmtObjC.h"
  17. #include "clang/StaticAnalyzer/Core/Checker.h"
  18. #include "clang/StaticAnalyzer/Core/CheckerManager.h"
  19. #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
  20. #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
  21. #include "llvm/Support/raw_ostream.h"
  22. using namespace clang;
  23. using namespace ento;
  24. namespace {
  25. class TraversalDumper : public Checker< check::BranchCondition,
  26. check::BeginFunction,
  27. check::EndFunction > {
  28. public:
  29. void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const;
  30. void checkBeginFunction(CheckerContext &C) const;
  31. void checkEndFunction(CheckerContext &C) const;
  32. };
  33. }
  34. void TraversalDumper::checkBranchCondition(const Stmt *Condition,
  35. CheckerContext &C) const {
  36. // Special-case Objective-C's for-in loop, which uses the entire loop as its
  37. // condition. We just print the collection expression.
  38. const Stmt *Parent = dyn_cast<ObjCForCollectionStmt>(Condition);
  39. if (!Parent) {
  40. const ParentMap &Parents = C.getLocationContext()->getParentMap();
  41. Parent = Parents.getParent(Condition);
  42. }
  43. // It is mildly evil to print directly to llvm::outs() rather than emitting
  44. // warnings, but this ensures things do not get filtered out by the rest of
  45. // the static analyzer machinery.
  46. SourceLocation Loc = Parent->getLocStart();
  47. llvm::outs() << C.getSourceManager().getSpellingLineNumber(Loc) << " "
  48. << Parent->getStmtClassName() << "\n";
  49. }
  50. void TraversalDumper::checkBeginFunction(CheckerContext &C) const {
  51. llvm::outs() << "--BEGIN FUNCTION--\n";
  52. }
  53. void TraversalDumper::checkEndFunction(CheckerContext &C) const {
  54. llvm::outs() << "--END FUNCTION--\n";
  55. }
  56. void ento::registerTraversalDumper(CheckerManager &mgr) {
  57. mgr.registerChecker<TraversalDumper>();
  58. }
  59. //------------------------------------------------------------------------------
  60. namespace {
  61. class CallDumper : public Checker< check::PreCall,
  62. check::PostCall > {
  63. public:
  64. void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
  65. void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
  66. };
  67. }
  68. void CallDumper::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
  69. unsigned Indentation = 0;
  70. for (const LocationContext *LC = C.getLocationContext()->getParent();
  71. LC != nullptr; LC = LC->getParent())
  72. ++Indentation;
  73. // It is mildly evil to print directly to llvm::outs() rather than emitting
  74. // warnings, but this ensures things do not get filtered out by the rest of
  75. // the static analyzer machinery.
  76. llvm::outs().indent(Indentation);
  77. Call.dump(llvm::outs());
  78. }
  79. void CallDumper::checkPostCall(const CallEvent &Call, CheckerContext &C) const {
  80. const Expr *CallE = Call.getOriginExpr();
  81. if (!CallE)
  82. return;
  83. unsigned Indentation = 0;
  84. for (const LocationContext *LC = C.getLocationContext()->getParent();
  85. LC != nullptr; LC = LC->getParent())
  86. ++Indentation;
  87. // It is mildly evil to print directly to llvm::outs() rather than emitting
  88. // warnings, but this ensures things do not get filtered out by the rest of
  89. // the static analyzer machinery.
  90. llvm::outs().indent(Indentation);
  91. if (Call.getResultType()->isVoidType())
  92. llvm::outs() << "Returning void\n";
  93. else
  94. llvm::outs() << "Returning " << C.getSVal(CallE) << "\n";
  95. }
  96. void ento::registerCallDumper(CheckerManager &mgr) {
  97. mgr.registerChecker<CallDumper>();
  98. }