clang API Documentation

TraversalChecker.cpp
Go to the documentation of this file.
00001 //== TraversalChecker.cpp -------------------------------------- -*- C++ -*--=//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // These checkers print various aspects of the ExprEngine's traversal of the CFG
00011 // as it builds the ExplodedGraph.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 #include "ClangSACheckers.h"
00015 #include "clang/AST/ParentMap.h"
00016 #include "clang/AST/StmtObjC.h"
00017 #include "clang/StaticAnalyzer/Core/Checker.h"
00018 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
00019 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
00020 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
00021 #include "llvm/Support/raw_ostream.h"
00022 
00023 using namespace clang;
00024 using namespace ento;
00025 
00026 namespace {
00027 class TraversalDumper : public Checker< check::BranchCondition,
00028                                         check::EndFunction > {
00029 public:
00030   void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const;
00031   void checkEndFunction(CheckerContext &C) const;
00032 };
00033 }
00034 
00035 void TraversalDumper::checkBranchCondition(const Stmt *Condition,
00036                                            CheckerContext &C) const {
00037   // Special-case Objective-C's for-in loop, which uses the entire loop as its
00038   // condition. We just print the collection expression.
00039   const Stmt *Parent = dyn_cast<ObjCForCollectionStmt>(Condition);
00040   if (!Parent) {
00041     const ParentMap &Parents = C.getLocationContext()->getParentMap();
00042     Parent = Parents.getParent(Condition);
00043   }
00044 
00045   // It is mildly evil to print directly to llvm::outs() rather than emitting
00046   // warnings, but this ensures things do not get filtered out by the rest of
00047   // the static analyzer machinery.
00048   SourceLocation Loc = Parent->getLocStart();
00049   llvm::outs() << C.getSourceManager().getSpellingLineNumber(Loc) << " "
00050                << Parent->getStmtClassName() << "\n";
00051 }
00052 
00053 void TraversalDumper::checkEndFunction(CheckerContext &C) const {
00054   llvm::outs() << "--END FUNCTION--\n";
00055 }
00056 
00057 void ento::registerTraversalDumper(CheckerManager &mgr) {
00058   mgr.registerChecker<TraversalDumper>();
00059 }
00060 
00061 //------------------------------------------------------------------------------
00062 
00063 namespace {
00064 class CallDumper : public Checker< check::PreCall,
00065                                    check::PostCall > {
00066 public:
00067   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
00068   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
00069 };
00070 }
00071 
00072 void CallDumper::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
00073   unsigned Indentation = 0;
00074   for (const LocationContext *LC = C.getLocationContext()->getParent();
00075        LC != nullptr; LC = LC->getParent())
00076     ++Indentation;
00077 
00078   // It is mildly evil to print directly to llvm::outs() rather than emitting
00079   // warnings, but this ensures things do not get filtered out by the rest of
00080   // the static analyzer machinery.
00081   llvm::outs().indent(Indentation);
00082   Call.dump(llvm::outs());
00083 }
00084 
00085 void CallDumper::checkPostCall(const CallEvent &Call, CheckerContext &C) const {
00086   const Expr *CallE = Call.getOriginExpr();
00087   if (!CallE)
00088     return;
00089 
00090   unsigned Indentation = 0;
00091   for (const LocationContext *LC = C.getLocationContext()->getParent();
00092        LC != nullptr; LC = LC->getParent())
00093     ++Indentation;
00094 
00095   // It is mildly evil to print directly to llvm::outs() rather than emitting
00096   // warnings, but this ensures things do not get filtered out by the rest of
00097   // the static analyzer machinery.
00098   llvm::outs().indent(Indentation);
00099   if (Call.getResultType()->isVoidType())
00100     llvm::outs() << "Returning void\n";
00101   else
00102     llvm::outs() << "Returning " << C.getSVal(CallE) << "\n";
00103 }
00104 
00105 void ento::registerCallDumper(CheckerManager &mgr) {
00106   mgr.registerChecker<CallDumper>();
00107 }