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