Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/StaticAnalyzer/Checkers/TraversalChecker.cpp
Line
Count
Source (jump to first uncovered line)
1
//== TraversalChecker.cpp -------------------------------------- -*- C++ -*--=//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// These checkers print various aspects of the ExprEngine's traversal of the CFG
10
// as it builds the ExplodedGraph.
11
//
12
//===----------------------------------------------------------------------===//
13
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
14
#include "clang/AST/ParentMap.h"
15
#include "clang/AST/StmtObjC.h"
16
#include "clang/StaticAnalyzer/Core/Checker.h"
17
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
18
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
19
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
20
#include "llvm/Support/raw_ostream.h"
21
22
using namespace clang;
23
using namespace ento;
24
25
namespace {
26
class TraversalDumper : public Checker< check::BranchCondition,
27
                                        check::BeginFunction,
28
                                        check::EndFunction > {
29
public:
30
  void checkBranchCondition(const Stmt *Condition, CheckerContext &C) const;
31
  void checkBeginFunction(CheckerContext &C) const;
32
  void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
33
};
34
}
35
36
void TraversalDumper::checkBranchCondition(const Stmt *Condition,
37
45
                                           CheckerContext &C) const {
38
  // Special-case Objective-C's for-in loop, which uses the entire loop as its
39
  // condition. We just print the collection expression.
40
45
  const Stmt *Parent = dyn_cast<ObjCForCollectionStmt>(Condition);
41
45
  if (!Parent) {
42
31
    const ParentMap &Parents = C.getLocationContext()->getParentMap();
43
31
    Parent = Parents.getParent(Condition);
44
31
  }
45
46
  // It is mildly evil to print directly to llvm::outs() rather than emitting
47
  // warnings, but this ensures things do not get filtered out by the rest of
48
  // the static analyzer machinery.
49
45
  SourceLocation Loc = Parent->getBeginLoc();
50
45
  llvm::outs() << C.getSourceManager().getSpellingLineNumber(Loc) << " "
51
45
               << Parent->getStmtClassName() << "\n";
52
45
}
53
54
8
void TraversalDumper::checkBeginFunction(CheckerContext &C) const {
55
8
  llvm::outs() << "--BEGIN FUNCTION--\n";
56
8
}
57
58
void TraversalDumper::checkEndFunction(const ReturnStmt *RS,
59
9
                                       CheckerContext &C) const {
60
9
  llvm::outs() << "--END FUNCTION--\n";
61
9
}
62
63
4
void ento::registerTraversalDumper(CheckerManager &mgr) {
64
4
  mgr.registerChecker<TraversalDumper>();
65
4
}
66
67
8
bool ento::shouldRegisterTraversalDumper(const CheckerManager &mgr) {
68
8
  return true;
69
8
}
70
71
//------------------------------------------------------------------------------
72
73
namespace {
74
class CallDumper : public Checker< check::PreCall,
75
                                   check::PostCall > {
76
public:
77
  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
78
  void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
79
};
80
}
81
82
0
void CallDumper::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
83
0
  unsigned Indentation = 0;
84
0
  for (const LocationContext *LC = C.getLocationContext()->getParent();
85
0
       LC != nullptr; LC = LC->getParent())
86
0
    ++Indentation;
87
88
  // It is mildly evil to print directly to llvm::outs() rather than emitting
89
  // warnings, but this ensures things do not get filtered out by the rest of
90
  // the static analyzer machinery.
91
0
  llvm::outs().indent(Indentation);
92
0
  Call.dump(llvm::outs());
93
0
}
94
95
0
void CallDumper::checkPostCall(const CallEvent &Call, CheckerContext &C) const {
96
0
  const Expr *CallE = Call.getOriginExpr();
97
0
  if (!CallE)
98
0
    return;
99
100
0
  unsigned Indentation = 0;
101
0
  for (const LocationContext *LC = C.getLocationContext()->getParent();
102
0
       LC != nullptr; LC = LC->getParent())
103
0
    ++Indentation;
104
105
  // It is mildly evil to print directly to llvm::outs() rather than emitting
106
  // warnings, but this ensures things do not get filtered out by the rest of
107
  // the static analyzer machinery.
108
0
  llvm::outs().indent(Indentation);
109
0
  if (Call.getResultType()->isVoidType())
110
0
    llvm::outs() << "Returning void\n";
111
0
  else
112
0
    llvm::outs() << "Returning " << C.getSVal(CallE) << "\n";
113
0
}
114
115
0
void ento::registerCallDumper(CheckerManager &mgr) {
116
0
  mgr.registerChecker<CallDumper>();
117
0
}
118
119
0
bool ento::shouldRegisterCallDumper(const CheckerManager &mgr) {
120
0
  return true;
121
0
}