TraversalChecker.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  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. // //
  23. ///////////////////////////////////////////////////////////////////////////////
  24. using namespace clang;
  25. using namespace ento;
  26. namespace {
  27. class TraversalDumper : public Checker< check::BranchCondition,
  28. check::EndFunction > {
  29. public:
  30. void checkBranchCondition(const Stmt *Condition, 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::checkEndFunction(CheckerContext &C) const {
  51. llvm::outs() << "--END FUNCTION--\n";
  52. }
  53. void ento::registerTraversalDumper(CheckerManager &mgr) {
  54. mgr.registerChecker<TraversalDumper>();
  55. }
  56. //------------------------------------------------------------------------------
  57. namespace {
  58. class CallDumper : public Checker< check::PreCall,
  59. check::PostCall > {
  60. public:
  61. void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
  62. void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
  63. };
  64. }
  65. void CallDumper::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
  66. unsigned Indentation = 0;
  67. for (const LocationContext *LC = C.getLocationContext()->getParent();
  68. LC != nullptr; LC = LC->getParent())
  69. ++Indentation;
  70. // It is mildly evil to print directly to llvm::outs() rather than emitting
  71. // warnings, but this ensures things do not get filtered out by the rest of
  72. // the static analyzer machinery.
  73. llvm::outs().indent(Indentation);
  74. Call.dump(llvm::outs());
  75. }
  76. void CallDumper::checkPostCall(const CallEvent &Call, CheckerContext &C) const {
  77. const Expr *CallE = Call.getOriginExpr();
  78. if (!CallE)
  79. return;
  80. unsigned Indentation = 0;
  81. for (const LocationContext *LC = C.getLocationContext()->getParent();
  82. LC != nullptr; LC = LC->getParent())
  83. ++Indentation;
  84. // It is mildly evil to print directly to llvm::outs() rather than emitting
  85. // warnings, but this ensures things do not get filtered out by the rest of
  86. // the static analyzer machinery.
  87. llvm::outs().indent(Indentation);
  88. if (Call.getResultType()->isVoidType())
  89. llvm::outs() << "Returning void\n";
  90. else
  91. llvm::outs() << "Returning " << C.getSVal(CallE) << "\n";
  92. }
  93. void ento::registerCallDumper(CheckerManager &mgr) {
  94. mgr.registerChecker<CallDumper>();
  95. }