Home | History | Annotate | Download | only in Checkers
      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 // These checkers print various aspects of the ExprEngine's traversal of the CFG
     11 // as it builds the ExplodedGraph.
     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/CallEvent.h"
     20 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
     21 #include "llvm/Support/raw_ostream.h"
     22 
     23 using namespace clang;
     24 using namespace ento;
     25 
     26 namespace {
     27 class TraversalDumper : public Checker< check::BranchCondition,
     28                                         check::EndFunction > {
     29 public:
     30   void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const;
     31   void checkEndFunction(CheckerContext &C) const;
     32 };
     33 }
     34 
     35 void TraversalDumper::checkBranchCondition(const Stmt *Condition,
     36                                            CheckerContext &C) const {
     37   // Special-case Objective-C's for-in loop, which uses the entire loop as its
     38   // condition. We just print the collection expression.
     39   const Stmt *Parent = dyn_cast<ObjCForCollectionStmt>(Condition);
     40   if (!Parent) {
     41     const ParentMap &Parents = C.getLocationContext()->getParentMap();
     42     Parent = Parents.getParent(Condition);
     43   }
     44 
     45   // It is mildly evil to print directly to llvm::outs() rather than emitting
     46   // warnings, but this ensures things do not get filtered out by the rest of
     47   // the static analyzer machinery.
     48   SourceLocation Loc = Parent->getLocStart();
     49   llvm::outs() << C.getSourceManager().getSpellingLineNumber(Loc) << " "
     50                << Parent->getStmtClassName() << "\n";
     51 }
     52 
     53 void TraversalDumper::checkEndFunction(CheckerContext &C) const {
     54   llvm::outs() << "--END FUNCTION--\n";
     55 }
     56 
     57 void ento::registerTraversalDumper(CheckerManager &mgr) {
     58   mgr.registerChecker<TraversalDumper>();
     59 }
     60 
     61 //------------------------------------------------------------------------------
     62 
     63 namespace {
     64 class CallDumper : public Checker< check::PreCall,
     65                                    check::PostCall > {
     66 public:
     67   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
     68   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
     69 };
     70 }
     71 
     72 void CallDumper::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
     73   unsigned Indentation = 0;
     74   for (const LocationContext *LC = C.getLocationContext()->getParent();
     75        LC != 0; LC = LC->getParent())
     76     ++Indentation;
     77 
     78   // It is mildly evil to print directly to llvm::outs() rather than emitting
     79   // warnings, but this ensures things do not get filtered out by the rest of
     80   // the static analyzer machinery.
     81   llvm::outs().indent(Indentation);
     82   Call.dump(llvm::outs());
     83 }
     84 
     85 void CallDumper::checkPostCall(const CallEvent &Call, CheckerContext &C) const {
     86   const Expr *CallE = Call.getOriginExpr();
     87   if (!CallE)
     88     return;
     89 
     90   unsigned Indentation = 0;
     91   for (const LocationContext *LC = C.getLocationContext()->getParent();
     92        LC != 0; LC = LC->getParent())
     93     ++Indentation;
     94 
     95   // It is mildly evil to print directly to llvm::outs() rather than emitting
     96   // warnings, but this ensures things do not get filtered out by the rest of
     97   // the static analyzer machinery.
     98   llvm::outs().indent(Indentation);
     99   if (Call.getResultType()->isVoidType())
    100     llvm::outs() << "Returning void\n";
    101   else
    102     llvm::outs() << "Returning " << C.getSVal(CallE) << "\n";
    103 }
    104 
    105 void ento::registerCallDumper(CheckerManager &mgr) {
    106   mgr.registerChecker<CallDumper>();
    107 }
    108