TraversalChecker.cpp 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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::EndPath > {
  27. public:
  28. void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const;
  29. void checkEndPath(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::checkEndPath(CheckerContext &C) const {
  49. llvm::outs() << "--END PATH--\n";
  50. }
  51. void ento::registerTraversalDumper(CheckerManager &mgr) {
  52. mgr.registerChecker<TraversalDumper>();
  53. }
  54. //------------------------------------------------------------------------------
  55. namespace {
  56. class CallDumper : public Checker< check::PreCall > {
  57. public:
  58. void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
  59. };
  60. }
  61. void CallDumper::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
  62. unsigned Indentation = 0;
  63. for (const LocationContext *LC = C.getLocationContext()->getParent();
  64. LC != 0; LC = LC->getParent())
  65. ++Indentation;
  66. // It is mildly evil to print directly to llvm::outs() rather than emitting
  67. // warnings, but this ensures things do not get filtered out by the rest of
  68. // the static analyzer machinery.
  69. llvm::outs().indent(Indentation);
  70. Call.dump(llvm::outs());
  71. }
  72. void ento::registerCallDumper(CheckerManager &mgr) {
  73. mgr.registerChecker<CallDumper>();
  74. }