18d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose//== TraversalChecker.cpp -------------------------------------- -*- C++ -*--=//
28d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose//
38d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose//                     The LLVM Compiler Infrastructure
48d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose//
58d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose// This file is distributed under the University of Illinois Open Source
68d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose// License. See LICENSE.TXT for details.
78d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose//
88d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose//===----------------------------------------------------------------------===//
98d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose//
100ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose// These checkers print various aspects of the ExprEngine's traversal of the CFG
110ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose// as it builds the ExplodedGraph.
128d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose//
138d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose//===----------------------------------------------------------------------===//
148d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose#include "ClangSACheckers.h"
158d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose#include "clang/AST/ParentMap.h"
168d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose#include "clang/AST/StmtObjC.h"
178d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose#include "clang/StaticAnalyzer/Core/Checker.h"
188d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose#include "clang/StaticAnalyzer/Core/CheckerManager.h"
19f540c54701e3eeb34cb619a3a4eb18f1ac70ef2dJordan Rose#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
208d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
218d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose
228d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Roseusing namespace clang;
238d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Roseusing namespace ento;
248d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose
258d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rosenamespace {
268d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Roseclass TraversalDumper : public Checker< check::BranchCondition,
278d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose                                        check::EndPath > {
288d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rosepublic:
298d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const;
308d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  void checkEndPath(CheckerContext &C) const;
318d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose};
328d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose}
338d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose
348d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rosevoid TraversalDumper::checkBranchCondition(const Stmt *Condition,
358d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose                                           CheckerContext &C) const {
368d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  // Special-case Objective-C's for-in loop, which uses the entire loop as its
378d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  // condition. We just print the collection expression.
388d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  const Stmt *Parent = dyn_cast<ObjCForCollectionStmt>(Condition);
398d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  if (!Parent) {
408d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose    const ParentMap &Parents = C.getLocationContext()->getParentMap();
418d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose    Parent = Parents.getParent(Condition);
428d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  }
438d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose
448d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  // It is mildly evil to print directly to llvm::outs() rather than emitting
458d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  // warnings, but this ensures things do not get filtered out by the rest of
468d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  // the static analyzer machinery.
478d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  SourceLocation Loc = Parent->getLocStart();
488d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  llvm::outs() << C.getSourceManager().getSpellingLineNumber(Loc) << " "
498d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose               << Parent->getStmtClassName() << "\n";
508d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose}
518d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose
528d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rosevoid TraversalDumper::checkEndPath(CheckerContext &C) const {
538d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  llvm::outs() << "--END PATH--\n";
548d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose}
558d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose
568d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rosevoid ento::registerTraversalDumper(CheckerManager &mgr) {
578d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  mgr.registerChecker<TraversalDumper>();
588d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose}
590ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose
600ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose//------------------------------------------------------------------------------
610ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose
620ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rosenamespace {
630ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Roseclass CallDumper : public Checker< check::PreCall > {
640ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rosepublic:
650ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
660ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose};
670ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose}
680ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose
690ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rosevoid CallDumper::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
700ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  unsigned Indentation = 0;
710ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  for (const LocationContext *LC = C.getLocationContext()->getParent();
720ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose       LC != 0; LC = LC->getParent())
730ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose    ++Indentation;
740ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose
750ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  // It is mildly evil to print directly to llvm::outs() rather than emitting
760ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  // warnings, but this ensures things do not get filtered out by the rest of
770ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  // the static analyzer machinery.
780ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  llvm::outs().indent(Indentation);
790ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  Call.dump(llvm::outs());
800ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose}
810ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose
820ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rosevoid ento::registerCallDumper(CheckerManager &mgr) {
830ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  mgr.registerChecker<CallDumper>();
840ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose}
85