TraversalChecker.cpp 4.4 KB

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