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"
21a93d0f280693b8418bc88cf7a8c93325f7fcf4c6Benjamin Kramer#include "llvm/Support/raw_ostream.h"
228d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose
238d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Roseusing namespace clang;
248d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Roseusing namespace ento;
258d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose
268d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rosenamespace {
278d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Roseclass TraversalDumper : public Checker< check::BranchCondition,
28344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks                                        check::EndFunction > {
298d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rosepublic:
308d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const;
31344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks  void checkEndFunction(CheckerContext &C) const;
328d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose};
338d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose}
348d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose
358d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rosevoid TraversalDumper::checkBranchCondition(const Stmt *Condition,
368d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose                                           CheckerContext &C) const {
378d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  // Special-case Objective-C's for-in loop, which uses the entire loop as its
388d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  // condition. We just print the collection expression.
398d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  const Stmt *Parent = dyn_cast<ObjCForCollectionStmt>(Condition);
408d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  if (!Parent) {
418d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose    const ParentMap &Parents = C.getLocationContext()->getParentMap();
428d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose    Parent = Parents.getParent(Condition);
438d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  }
448d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose
458d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  // It is mildly evil to print directly to llvm::outs() rather than emitting
468d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  // warnings, but this ensures things do not get filtered out by the rest of
478d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  // the static analyzer machinery.
488d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  SourceLocation Loc = Parent->getLocStart();
498d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  llvm::outs() << C.getSourceManager().getSpellingLineNumber(Loc) << " "
508d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose               << Parent->getStmtClassName() << "\n";
518d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose}
528d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose
53344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaksvoid TraversalDumper::checkEndFunction(CheckerContext &C) const {
54344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks  llvm::outs() << "--END FUNCTION--\n";
558d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose}
568d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose
578d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rosevoid ento::registerTraversalDumper(CheckerManager &mgr) {
588d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose  mgr.registerChecker<TraversalDumper>();
598d0f528afd9fcb9ebb8ccb4b8a529a05375b628eJordan Rose}
600ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose
610ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose//------------------------------------------------------------------------------
620ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose
630ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rosenamespace {
64f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Roseclass CallDumper : public Checker< check::PreCall,
65f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose                                   check::PostCall > {
660ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rosepublic:
670ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
68f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose  void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
690ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose};
700ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose}
710ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose
720ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rosevoid CallDumper::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
730ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  unsigned Indentation = 0;
740ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  for (const LocationContext *LC = C.getLocationContext()->getParent();
750ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose       LC != 0; LC = LC->getParent())
760ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose    ++Indentation;
770ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose
780ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  // It is mildly evil to print directly to llvm::outs() rather than emitting
790ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  // warnings, but this ensures things do not get filtered out by the rest of
800ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  // the static analyzer machinery.
810ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  llvm::outs().indent(Indentation);
820ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  Call.dump(llvm::outs());
830ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose}
840ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose
85f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rosevoid CallDumper::checkPostCall(const CallEvent &Call, CheckerContext &C) const {
86f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose  const Expr *CallE = Call.getOriginExpr();
87f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose  if (!CallE)
88f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose    return;
89f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose
90f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose  unsigned Indentation = 0;
91f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose  for (const LocationContext *LC = C.getLocationContext()->getParent();
92f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose       LC != 0; LC = LC->getParent())
93f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose    ++Indentation;
94f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose
95f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose  // It is mildly evil to print directly to llvm::outs() rather than emitting
96f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose  // warnings, but this ensures things do not get filtered out by the rest of
97f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose  // the static analyzer machinery.
98f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose  llvm::outs().indent(Indentation);
99f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose  if (Call.getResultType()->isVoidType())
100f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose    llvm::outs() << "Returning void\n";
101f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose  else
102f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose    llvm::outs() << "Returning " << C.getSVal(CallE) << "\n";
103f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose}
104f3e426b22a36fc31c00ebf7c0de3aa445758b7e6Jordan Rose
1050ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rosevoid ento::registerCallDumper(CheckerManager &mgr) {
1060ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose  mgr.registerChecker<CallDumper>();
1070ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose}
108