TraversalChecker.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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::EndFunction > {
  27. public:
  28. void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const;
  29. void checkEndFunction(CheckerContext &C) const;
  30. };
  31. }
  32. void TraversalDumper::checkBranchCondition(const Stmt *Condition,
  33. CheckerContext &C) const {
  34. // Special-case Objective-C's for-in loop, which uses the entire loop as its
  35. // condition. We just print the collection expression.
  36. const Stmt *Parent = dyn_cast<ObjCForCollectionStmt>(Condition);
  37. if (!Parent) {
  38. const ParentMap &Parents = C.getLocationContext()->getParentMap();
  39. Parent = Parents.getParent(Condition);
  40. }
  41. // It is mildly evil to print directly to llvm::outs() rather than emitting
  42. // warnings, but this ensures things do not get filtered out by the rest of
  43. // the static analyzer machinery.
  44. SourceLocation Loc = Parent->getLocStart();
  45. llvm::outs() << C.getSourceManager().getSpellingLineNumber(Loc) << " "
  46. << Parent->getStmtClassName() << "\n";
  47. }
  48. void TraversalDumper::checkEndFunction(CheckerContext &C) const {
  49. llvm::outs() << "--END FUNCTION--\n";
  50. }
  51. void ento::registerTraversalDumper(CheckerManager &mgr) {
  52. mgr.registerChecker<TraversalDumper>();
  53. }
  54. //------------------------------------------------------------------------------
  55. namespace {
  56. class CallDumper : public Checker< check::PreCall,
  57. check::PostCall > {
  58. public:
  59. void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
  60. void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
  61. };
  62. }
  63. void CallDumper::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
  64. unsigned Indentation = 0;
  65. for (const LocationContext *LC = C.getLocationContext()->getParent();
  66. LC != nullptr; LC = LC->getParent())
  67. ++Indentation;
  68. // It is mildly evil to print directly to llvm::outs() rather than emitting
  69. // warnings, but this ensures things do not get filtered out by the rest of
  70. // the static analyzer machinery.
  71. llvm::outs().indent(Indentation);
  72. Call.dump(llvm::outs());
  73. }
  74. void CallDumper::checkPostCall(const CallEvent &Call, CheckerContext &C) const {
  75. const Expr *CallE = Call.getOriginExpr();
  76. if (!CallE)
  77. return;
  78. unsigned Indentation = 0;
  79. for (const LocationContext *LC = C.getLocationContext()->getParent();
  80. LC != nullptr; LC = LC->getParent())
  81. ++Indentation;
  82. // It is mildly evil to print directly to llvm::outs() rather than emitting
  83. // warnings, but this ensures things do not get filtered out by the rest of
  84. // the static analyzer machinery.
  85. llvm::outs().indent(Indentation);
  86. if (Call.getResultType()->isVoidType())
  87. llvm::outs() << "Returning void\n";
  88. else
  89. llvm::outs() << "Returning " << C.getSVal(CallE) << "\n";
  90. }
  91. void ento::registerCallDumper(CheckerManager &mgr) {
  92. mgr.registerChecker<CallDumper>();
  93. }