1f4a2713aSLionel Sambuc //== TraversalChecker.cpp -------------------------------------- -*- C++ -*--=//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // These checkers print various aspects of the ExprEngine's traversal of the CFG
11f4a2713aSLionel Sambuc // as it builds the ExplodedGraph.
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc #include "ClangSACheckers.h"
15f4a2713aSLionel Sambuc #include "clang/AST/ParentMap.h"
16f4a2713aSLionel Sambuc #include "clang/AST/StmtObjC.h"
17f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/Checker.h"
18f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/CheckerManager.h"
19f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
20f4a2713aSLionel Sambuc #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
21f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
22f4a2713aSLionel Sambuc
23f4a2713aSLionel Sambuc using namespace clang;
24f4a2713aSLionel Sambuc using namespace ento;
25f4a2713aSLionel Sambuc
26f4a2713aSLionel Sambuc namespace {
27f4a2713aSLionel Sambuc class TraversalDumper : public Checker< check::BranchCondition,
28f4a2713aSLionel Sambuc check::EndFunction > {
29f4a2713aSLionel Sambuc public:
30f4a2713aSLionel Sambuc void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const;
31f4a2713aSLionel Sambuc void checkEndFunction(CheckerContext &C) const;
32f4a2713aSLionel Sambuc };
33f4a2713aSLionel Sambuc }
34f4a2713aSLionel Sambuc
checkBranchCondition(const Stmt * Condition,CheckerContext & C) const35f4a2713aSLionel Sambuc void TraversalDumper::checkBranchCondition(const Stmt *Condition,
36f4a2713aSLionel Sambuc CheckerContext &C) const {
37f4a2713aSLionel Sambuc // Special-case Objective-C's for-in loop, which uses the entire loop as its
38f4a2713aSLionel Sambuc // condition. We just print the collection expression.
39f4a2713aSLionel Sambuc const Stmt *Parent = dyn_cast<ObjCForCollectionStmt>(Condition);
40f4a2713aSLionel Sambuc if (!Parent) {
41f4a2713aSLionel Sambuc const ParentMap &Parents = C.getLocationContext()->getParentMap();
42f4a2713aSLionel Sambuc Parent = Parents.getParent(Condition);
43f4a2713aSLionel Sambuc }
44f4a2713aSLionel Sambuc
45f4a2713aSLionel Sambuc // It is mildly evil to print directly to llvm::outs() rather than emitting
46f4a2713aSLionel Sambuc // warnings, but this ensures things do not get filtered out by the rest of
47f4a2713aSLionel Sambuc // the static analyzer machinery.
48f4a2713aSLionel Sambuc SourceLocation Loc = Parent->getLocStart();
49f4a2713aSLionel Sambuc llvm::outs() << C.getSourceManager().getSpellingLineNumber(Loc) << " "
50f4a2713aSLionel Sambuc << Parent->getStmtClassName() << "\n";
51f4a2713aSLionel Sambuc }
52f4a2713aSLionel Sambuc
checkEndFunction(CheckerContext & C) const53f4a2713aSLionel Sambuc void TraversalDumper::checkEndFunction(CheckerContext &C) const {
54f4a2713aSLionel Sambuc llvm::outs() << "--END FUNCTION--\n";
55f4a2713aSLionel Sambuc }
56f4a2713aSLionel Sambuc
registerTraversalDumper(CheckerManager & mgr)57f4a2713aSLionel Sambuc void ento::registerTraversalDumper(CheckerManager &mgr) {
58f4a2713aSLionel Sambuc mgr.registerChecker<TraversalDumper>();
59f4a2713aSLionel Sambuc }
60f4a2713aSLionel Sambuc
61f4a2713aSLionel Sambuc //------------------------------------------------------------------------------
62f4a2713aSLionel Sambuc
63f4a2713aSLionel Sambuc namespace {
64f4a2713aSLionel Sambuc class CallDumper : public Checker< check::PreCall,
65f4a2713aSLionel Sambuc check::PostCall > {
66f4a2713aSLionel Sambuc public:
67f4a2713aSLionel Sambuc void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
68f4a2713aSLionel Sambuc void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
69f4a2713aSLionel Sambuc };
70f4a2713aSLionel Sambuc }
71f4a2713aSLionel Sambuc
checkPreCall(const CallEvent & Call,CheckerContext & C) const72f4a2713aSLionel Sambuc void CallDumper::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
73f4a2713aSLionel Sambuc unsigned Indentation = 0;
74f4a2713aSLionel Sambuc for (const LocationContext *LC = C.getLocationContext()->getParent();
75*0a6a1f1dSLionel Sambuc LC != nullptr; LC = LC->getParent())
76f4a2713aSLionel Sambuc ++Indentation;
77f4a2713aSLionel Sambuc
78f4a2713aSLionel Sambuc // It is mildly evil to print directly to llvm::outs() rather than emitting
79f4a2713aSLionel Sambuc // warnings, but this ensures things do not get filtered out by the rest of
80f4a2713aSLionel Sambuc // the static analyzer machinery.
81f4a2713aSLionel Sambuc llvm::outs().indent(Indentation);
82f4a2713aSLionel Sambuc Call.dump(llvm::outs());
83f4a2713aSLionel Sambuc }
84f4a2713aSLionel Sambuc
checkPostCall(const CallEvent & Call,CheckerContext & C) const85f4a2713aSLionel Sambuc void CallDumper::checkPostCall(const CallEvent &Call, CheckerContext &C) const {
86f4a2713aSLionel Sambuc const Expr *CallE = Call.getOriginExpr();
87f4a2713aSLionel Sambuc if (!CallE)
88f4a2713aSLionel Sambuc return;
89f4a2713aSLionel Sambuc
90f4a2713aSLionel Sambuc unsigned Indentation = 0;
91f4a2713aSLionel Sambuc for (const LocationContext *LC = C.getLocationContext()->getParent();
92*0a6a1f1dSLionel Sambuc LC != nullptr; LC = LC->getParent())
93f4a2713aSLionel Sambuc ++Indentation;
94f4a2713aSLionel Sambuc
95f4a2713aSLionel Sambuc // It is mildly evil to print directly to llvm::outs() rather than emitting
96f4a2713aSLionel Sambuc // warnings, but this ensures things do not get filtered out by the rest of
97f4a2713aSLionel Sambuc // the static analyzer machinery.
98f4a2713aSLionel Sambuc llvm::outs().indent(Indentation);
99f4a2713aSLionel Sambuc if (Call.getResultType()->isVoidType())
100f4a2713aSLionel Sambuc llvm::outs() << "Returning void\n";
101f4a2713aSLionel Sambuc else
102f4a2713aSLionel Sambuc llvm::outs() << "Returning " << C.getSVal(CallE) << "\n";
103f4a2713aSLionel Sambuc }
104f4a2713aSLionel Sambuc
registerCallDumper(CheckerManager & mgr)105f4a2713aSLionel Sambuc void ento::registerCallDumper(CheckerManager &mgr) {
106f4a2713aSLionel Sambuc mgr.registerChecker<CallDumper>();
107f4a2713aSLionel Sambuc }
108