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