]> granicus.if.org Git - clang/commitdiff
[analyzer] Add debug.DumpCalls, which prints out any CallEvents it sees.
authorJordan Rose <jordan_rose@apple.com>
Tue, 10 Jul 2012 23:56:23 +0000 (23:56 +0000)
committerJordan Rose <jordan_rose@apple.com>
Tue, 10 Jul 2012 23:56:23 +0000 (23:56 +0000)
This is probably not so useful yet because it is not path-sensitive, though
it does try to show inlining with indentation.

This also adds a dump() method to CallEvent, which should be useful for
debugging.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160030 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/StaticAnalyzer/Core/PathSensitive/Calls.h
lib/StaticAnalyzer/Checkers/Checkers.td
lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
lib/StaticAnalyzer/Core/Calls.cpp

index 4d64fd83a62569a13632be1add2bee3aeef67435..77eb3bea74ad36b6eb405c6fc9e93ef65b4975aa 100644 (file)
@@ -216,6 +216,10 @@ public:
     return llvm::map_iterator(param_end(), get_type_fun(&ParmVarDecl::getType));
   }
 
+  // For debugging purposes only
+  virtual void dump(raw_ostream &Out) const;
+  LLVM_ATTRIBUTE_USED void dump() const { dump(llvm::errs()); }
+
   static bool classof(const CallEvent *) { return true; }
 };
 
index 0969053976b4aa21ba0d0432f601263d3fb1de89..99410def2cae317fb1846b5925f92762503d3088 100644 (file)
@@ -483,6 +483,10 @@ def TraversalDumper : Checker<"DumpTraversal">,
   HelpText<"Print branch conditions as they are traversed by the engine">,
   DescFile<"TraversalChecker.cpp">;
 
+def CallDumper : Checker<"DumpCalls">,
+  HelpText<"Print calls as they are traversed by the engine">,
+  DescFile<"TraversalChecker.cpp">;
+
 def AnalyzerStatsChecker : Checker<"Stats">,
   HelpText<"Emit warnings with analyzer statistics">,
   DescFile<"AnalyzerStatsChecker.cpp">;
index d0479d451943e7e739b5797dc97fe0168298c575..ed6187de9ccf22a3540abf2abe16f9220400c493 100644 (file)
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This checker prints branch statements to llvm::outs as they are encountered.
-// This lets us see exactly how the ExprEngine is traversing the graph.
+// These checkers print various aspects of the ExprEngine's traversal of the CFG
+// as it builds the ExplodedGraph.
 //
 //===----------------------------------------------------------------------===//
 #include "ClangSACheckers.h"
@@ -16,6 +16,7 @@
 #include "clang/AST/StmtObjC.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 
 using namespace clang;
@@ -55,3 +56,29 @@ void TraversalDumper::checkEndPath(CheckerContext &C) const {
 void ento::registerTraversalDumper(CheckerManager &mgr) {
   mgr.registerChecker<TraversalDumper>();
 }
+
+//------------------------------------------------------------------------------
+
+namespace {
+class CallDumper : public Checker< check::PreCall > {
+public:
+  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
+};
+}
+
+void CallDumper::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
+  unsigned Indentation = 0;
+  for (const LocationContext *LC = C.getLocationContext()->getParent();
+       LC != 0; LC = LC->getParent())
+    ++Indentation;
+
+  // It is mildly evil to print directly to llvm::outs() rather than emitting
+  // warnings, but this ensures things do not get filtered out by the rest of
+  // the static analyzer machinery.
+  llvm::outs().indent(Indentation);
+  Call.dump(llvm::outs());
+}
+
+void ento::registerCallDumper(CheckerManager &mgr) {
+  mgr.registerChecker<CallDumper>();
+}
index ced1154da755f31b8a00d19d81cdb139a1594b84..94fc5fc8c054b3ebd9650cb7c4522cbb4c8fcd7a 100644 (file)
@@ -310,6 +310,24 @@ const FunctionDecl *SimpleCall::getDecl() const {
   return getSVal(CE->getCallee()).getAsFunctionDecl();
 }
 
+void CallEvent::dump(raw_ostream &Out) const {
+  ASTContext &Ctx = State->getStateManager().getContext();
+  if (const Expr *E = getOriginExpr()) {
+    E->printPretty(Out, Ctx, 0, Ctx.getLangOpts());
+    Out << "\n";
+    return;
+  }
+
+  if (const Decl *D = getDecl()) {
+    Out << "Call to ";
+    D->print(Out, Ctx.getLangOpts());
+    return;
+  }
+
+  // FIXME: a string representation of the kind would be nice.
+  Out << "Unknown call (type " << getKind() << ")";
+}
+
 
 SVal CXXMemberCall::getCXXThisVal() const {
   const Expr *Base = getOriginExpr()->getImplicitObjectArgument();