TraversalChecker.cpp revision 8d0f528afd9fcb9ebb8ccb4b8a529a05375b628e
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// This checker prints branch statements to llvm::outs as they are encountered.
11// This lets us see exactly how the ExprEngine is traversing the graph.
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/CheckerContext.h"
20
21using namespace clang;
22using namespace ento;
23
24namespace {
25class TraversalDumper : public Checker< check::BranchCondition,
26                                        check::EndPath > {
27public:
28  void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const;
29  void checkEndPath(CheckerContext &C) const;
30};
31}
32
33void 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
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
51void TraversalDumper::checkEndPath(CheckerContext &C) const {
52  llvm::outs() << "--END PATH--\n";
53}
54
55void ento::registerTraversalDumper(CheckerManager &mgr) {
56  mgr.registerChecker<TraversalDumper>();
57}
58