Coverage Report

Created: 2020-02-15 09:57

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- CheckerManager.cpp - Static Analyzer Checker Manager ---------------===//
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
// Defines the Static Analyzer Checker Manager.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
14
#include "clang/AST/DeclBase.h"
15
#include "clang/AST/Stmt.h"
16
#include "clang/Analysis/ProgramPoint.h"
17
#include "clang/Basic/JsonSupport.h"
18
#include "clang/Basic/LLVM.h"
19
#include "clang/Driver/DriverDiagnostic.h"
20
#include "clang/StaticAnalyzer/Core/Checker.h"
21
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
22
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
23
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
24
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
25
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
26
#include "llvm/ADT/SmallVector.h"
27
#include "llvm/Support/Casting.h"
28
#include "llvm/Support/ErrorHandling.h"
29
#include <cassert>
30
#include <vector>
31
32
using namespace clang;
33
using namespace ento;
34
35
14.0k
bool CheckerManager::hasPathSensitiveCheckers() const {
36
14.0k
  return !StmtCheckers.empty()              ||
37
14.0k
         
!PreObjCMessageCheckers.empty()1.90k
||
38
14.0k
         
!PostObjCMessageCheckers.empty()1.90k
||
39
14.0k
         
!PreCallCheckers.empty()1.77k
||
40
14.0k
         
!PostCallCheckers.empty()1.72k
||
41
14.0k
         
!LocationCheckers.empty()1.53k
||
42
14.0k
         
!BindCheckers.empty()1.50k
||
43
14.0k
         
!EndAnalysisCheckers.empty()1.50k
||
44
14.0k
         
!EndFunctionCheckers.empty()1.46k
||
45
14.0k
         
!BranchConditionCheckers.empty()1.46k
||
46
14.0k
         
!LiveSymbolsCheckers.empty()1.46k
||
47
14.0k
         
!DeadSymbolsCheckers.empty()1.46k
||
48
14.0k
         
!RegionChangesCheckers.empty()1.44k
||
49
14.0k
         
!EvalAssumeCheckers.empty()1.44k
||
50
14.0k
         
!EvalCallCheckers.empty()1.44k
;
51
14.0k
}
52
53
1.24k
void CheckerManager::finishedCheckerRegistration() {
54
1.24k
#ifndef NDEBUG
55
1.24k
  // Make sure that for every event that has listeners, there is at least
56
1.24k
  // one dispatcher registered for it.
57
1.24k
  for (const auto &Event : Events)
58
1.24k
    assert(Event.second.HasDispatcher &&
59
1.24k
           "No dispatcher registered for an event");
60
1.24k
#endif
61
1.24k
}
62
63
void CheckerManager::reportInvalidCheckerOptionValue(
64
6
    const CheckerBase *C, StringRef OptionName, StringRef ExpectedValueDesc) {
65
6
66
6
  Context.getDiagnostics()
67
6
      .Report(diag::err_analyzer_checker_option_invalid_input)
68
6
          << (llvm::Twine() + C->getTagDescription() + ":" + OptionName).str()
69
6
          << ExpectedValueDesc;
70
6
}
71
72
//===----------------------------------------------------------------------===//
73
// Functions for running checkers for AST traversing..
74
//===----------------------------------------------------------------------===//
75
76
void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
77
74.3k
                                          BugReporter &BR) {
78
74.3k
  assert(D);
79
74.3k
80
74.3k
  unsigned DeclKind = D->getKind();
81
74.3k
  CachedDeclCheckers *checkers = nullptr;
82
74.3k
  CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
83
74.3k
  if (CCI != CachedDeclCheckersMap.end()) {
84
65.3k
    checkers = &(CCI->second);
85
65.3k
  } else {
86
8.93k
    // Find the checkers that should run for this Decl and cache them.
87
8.93k
    checkers = &CachedDeclCheckersMap[DeclKind];
88
8.93k
    for (const auto &info : DeclCheckers)
89
1.46k
      if (info.IsForDeclFn(D))
90
90
        checkers->push_back(info.CheckFn);
91
8.93k
  }
92
74.3k
93
74.3k
  assert(checkers);
94
74.3k
  for (const auto &checker : *checkers)
95
646
    checker(D, mgr, BR);
96
74.3k
}
97
98
void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
99
16.1k
                                          BugReporter &BR) {
100
16.1k
  assert(D && D->hasBody());
101
16.1k
102
16.1k
  for (const auto &BodyChecker : BodyCheckers)
103
7.70k
    BodyChecker(D, mgr, BR);
104
16.1k
}
105
106
//===----------------------------------------------------------------------===//
107
// Functions for running checkers for path-sensitive checking.
108
//===----------------------------------------------------------------------===//
109
110
template <typename CHECK_CTX>
111
static void expandGraphWithCheckers(CHECK_CTX checkCtx,
112
                                    ExplodedNodeSet &Dst,
113
3.01M
                                    const ExplodedNodeSet &Src) {
114
3.01M
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
3.01M
  if (Src.empty())
116
127k
    return;
117
2.88M
118
2.88M
  typename CHECK_CTX::CheckersTy::const_iterator
119
2.88M
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
2.88M
  if (I == E) {
121
918k
    Dst.insert(Src);
122
918k
    return;
123
918k
  }
124
1.96M
125
1.96M
  ExplodedNodeSet Tmp1, Tmp2;
126
1.96M
  const ExplodedNodeSet *PrevSet = &Src;
127
1.96M
128
6.09M
  for (; I != E; 
++I4.13M
) {
129
4.13M
    ExplodedNodeSet *CurrSet = nullptr;
130
4.13M
    if (I+1 == E)
131
1.96M
      CurrSet = &Dst;
132
2.17M
    else {
133
2.17M
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp2683k
:
&Tmp11.48M
;
134
2.17M
      CurrSet->clear();
135
2.17M
    }
136
4.13M
137
4.13M
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
4.13M
    for (const auto &NI : *PrevSet)
139
4.13M
      checkCtx.runChecker(*I, B, NI);
140
4.13M
141
4.13M
    // If all the produced transitions are sinks, stop.
142
4.13M
    if (CurrSet->empty())
143
3.61k
      return;
144
4.13M
145
4.13M
    // Update which NodeSet is the current one.
146
4.13M
    PrevSet = CurrSet;
147
4.13M
  }
148
1.96M
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckStmtContext>((anonymous namespace)::CheckStmtContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
1.76M
                                    const ExplodedNodeSet &Src) {
114
1.76M
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
1.76M
  if (Src.empty())
116
60.8k
    return;
117
1.70M
118
1.70M
  typename CHECK_CTX::CheckersTy::const_iterator
119
1.70M
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
1.70M
  if (I == E) {
121
829k
    Dst.insert(Src);
122
829k
    return;
123
829k
  }
124
876k
125
876k
  ExplodedNodeSet Tmp1, Tmp2;
126
876k
  const ExplodedNodeSet *PrevSet = &Src;
127
876k
128
2.03M
  for (; I != E; 
++I1.15M
) {
129
1.15M
    ExplodedNodeSet *CurrSet = nullptr;
130
1.15M
    if (I+1 == E)
131
876k
      CurrSet = &Dst;
132
278k
    else {
133
278k
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp225.5k
:
&Tmp1253k
;
134
278k
      CurrSet->clear();
135
278k
    }
136
1.15M
137
1.15M
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
1.15M
    for (const auto &NI : *PrevSet)
139
1.15M
      checkCtx.runChecker(*I, B, NI);
140
1.15M
141
1.15M
    // If all the produced transitions are sinks, stop.
142
1.15M
    if (CurrSet->empty())
143
737
      return;
144
1.15M
145
1.15M
    // Update which NodeSet is the current one.
146
1.15M
    PrevSet = CurrSet;
147
1.15M
  }
148
876k
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckObjCMessageContext>((anonymous namespace)::CheckObjCMessageContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
8.73k
                                    const ExplodedNodeSet &Src) {
114
8.73k
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
8.73k
  if (Src.empty())
116
662
    return;
117
8.07k
118
8.07k
  typename CHECK_CTX::CheckersTy::const_iterator
119
8.07k
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
8.07k
  if (I == E) {
121
110
    Dst.insert(Src);
122
110
    return;
123
110
  }
124
7.96k
125
7.96k
  ExplodedNodeSet Tmp1, Tmp2;
126
7.96k
  const ExplodedNodeSet *PrevSet = &Src;
127
7.96k
128
25.8k
  for (; I != E; 
++I17.8k
) {
129
17.9k
    ExplodedNodeSet *CurrSet = nullptr;
130
17.9k
    if (I+1 == E)
131
7.95k
      CurrSet = &Dst;
132
9.97k
    else {
133
9.97k
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp22.95k
:
&Tmp17.02k
;
134
9.97k
      CurrSet->clear();
135
9.97k
    }
136
17.9k
137
17.9k
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
17.9k
    for (const auto &NI : *PrevSet)
139
17.9k
      checkCtx.runChecker(*I, B, NI);
140
17.9k
141
17.9k
    // If all the produced transitions are sinks, stop.
142
17.9k
    if (CurrSet->empty())
143
77
      return;
144
17.8k
145
17.8k
    // Update which NodeSet is the current one.
146
17.8k
    PrevSet = CurrSet;
147
17.8k
  }
148
7.96k
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckCallContext>((anonymous namespace)::CheckCallContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
340k
                                    const ExplodedNodeSet &Src) {
114
340k
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
340k
  if (Src.empty())
116
65.5k
    return;
117
274k
118
274k
  typename CHECK_CTX::CheckersTy::const_iterator
119
274k
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
274k
  if (I == E) {
121
4.59k
    Dst.insert(Src);
122
4.59k
    return;
123
4.59k
  }
124
270k
125
270k
  ExplodedNodeSet Tmp1, Tmp2;
126
270k
  const ExplodedNodeSet *PrevSet = &Src;
127
270k
128
1.25M
  for (; I != E; 
++I981k
) {
129
983k
    ExplodedNodeSet *CurrSet = nullptr;
130
983k
    if (I+1 == E)
131
269k
      CurrSet = &Dst;
132
713k
    else {
133
713k
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp2261k
:
&Tmp1451k
;
134
713k
      CurrSet->clear();
135
713k
    }
136
983k
137
983k
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
983k
    for (const auto &NI : *PrevSet)
139
983k
      checkCtx.runChecker(*I, B, NI);
140
983k
141
983k
    // If all the produced transitions are sinks, stop.
142
983k
    if (CurrSet->empty())
143
1.39k
      return;
144
981k
145
981k
    // Update which NodeSet is the current one.
146
981k
    PrevSet = CurrSet;
147
981k
  }
148
270k
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckLocationContext>((anonymous namespace)::CheckLocationContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
210k
                                    const ExplodedNodeSet &Src) {
114
210k
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
210k
  if (Src.empty())
116
0
    return;
117
210k
118
210k
  typename CHECK_CTX::CheckersTy::const_iterator
119
210k
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
210k
  if (I == E) {
121
4.26k
    Dst.insert(Src);
122
4.26k
    return;
123
4.26k
  }
124
206k
125
206k
  ExplodedNodeSet Tmp1, Tmp2;
126
206k
  const ExplodedNodeSet *PrevSet = &Src;
127
206k
128
708k
  for (; I != E; 
++I502k
) {
129
503k
    ExplodedNodeSet *CurrSet = nullptr;
130
503k
    if (I+1 == E)
131
206k
      CurrSet = &Dst;
132
297k
    else {
133
297k
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp290.5k
:
&Tmp1206k
;
134
297k
      CurrSet->clear();
135
297k
    }
136
503k
137
503k
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
503k
    for (const auto &NI : *PrevSet)
139
503k
      checkCtx.runChecker(*I, B, NI);
140
503k
141
503k
    // If all the produced transitions are sinks, stop.
142
503k
    if (CurrSet->empty())
143
989
      return;
144
502k
145
502k
    // Update which NodeSet is the current one.
146
502k
    PrevSet = CurrSet;
147
502k
  }
148
206k
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckBindContext>((anonymous namespace)::CheckBindContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
83.6k
                                    const ExplodedNodeSet &Src) {
114
83.6k
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
83.6k
  if (Src.empty())
116
0
    return;
117
83.6k
118
83.6k
  typename CHECK_CTX::CheckersTy::const_iterator
119
83.6k
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
83.6k
  if (I == E) {
121
1.59k
    Dst.insert(Src);
122
1.59k
    return;
123
1.59k
  }
124
82.0k
125
82.0k
  ExplodedNodeSet Tmp1, Tmp2;
126
82.0k
  const ExplodedNodeSet *PrevSet = &Src;
127
82.0k
128
252k
  for (; I != E; 
++I169k
) {
129
170k
    ExplodedNodeSet *CurrSet = nullptr;
130
170k
    if (I+1 == E)
131
82.0k
      CurrSet = &Dst;
132
88.2k
    else {
133
88.2k
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp25.74k
:
&Tmp182.4k
;
134
88.2k
      CurrSet->clear();
135
88.2k
    }
136
170k
137
170k
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
170k
    for (const auto &NI : *PrevSet)
139
170k
      checkCtx.runChecker(*I, B, NI);
140
170k
141
170k
    // If all the produced transitions are sinks, stop.
142
170k
    if (CurrSet->empty())
143
342
      return;
144
169k
145
169k
    // Update which NodeSet is the current one.
146
169k
    PrevSet = CurrSet;
147
169k
  }
148
82.0k
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckBeginFunctionContext>((anonymous namespace)::CheckBeginFunctionContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
76.3k
                                    const ExplodedNodeSet &Src) {
114
76.3k
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
76.3k
  if (Src.empty())
116
0
    return;
117
76.3k
118
76.3k
  typename CHECK_CTX::CheckersTy::const_iterator
119
76.3k
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
76.3k
  if (I == E) {
121
68.3k
    Dst.insert(Src);
122
68.3k
    return;
123
68.3k
  }
124
7.99k
125
7.99k
  ExplodedNodeSet Tmp1, Tmp2;
126
7.99k
  const ExplodedNodeSet *PrevSet = &Src;
127
7.99k
128
22.0k
  for (; I != E; 
++I14.0k
) {
129
14.0k
    ExplodedNodeSet *CurrSet = nullptr;
130
14.0k
    if (I+1 == E)
131
7.99k
      CurrSet = &Dst;
132
6.08k
    else {
133
6.08k
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp24
:
&Tmp16.07k
;
134
6.08k
      CurrSet->clear();
135
6.08k
    }
136
14.0k
137
14.0k
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
14.0k
    for (const auto &NI : *PrevSet)
139
14.0k
      checkCtx.runChecker(*I, B, NI);
140
14.0k
141
14.0k
    // If all the produced transitions are sinks, stop.
142
14.0k
    if (CurrSet->empty())
143
0
      return;
144
14.0k
145
14.0k
    // Update which NodeSet is the current one.
146
14.0k
    PrevSet = CurrSet;
147
14.0k
  }
148
7.99k
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckBranchConditionContext>((anonymous namespace)::CheckBranchConditionContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
47.2k
                                    const ExplodedNodeSet &Src) {
114
47.2k
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
47.2k
  if (Src.empty())
116
0
    return;
117
47.2k
118
47.2k
  typename CHECK_CTX::CheckersTy::const_iterator
119
47.2k
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
47.2k
  if (I == E) {
121
1.06k
    Dst.insert(Src);
122
1.06k
    return;
123
1.06k
  }
124
46.2k
125
46.2k
  ExplodedNodeSet Tmp1, Tmp2;
126
46.2k
  const ExplodedNodeSet *PrevSet = &Src;
127
46.2k
128
93.7k
  for (; I != E; 
++I47.5k
) {
129
47.6k
    ExplodedNodeSet *CurrSet = nullptr;
130
47.6k
    if (I+1 == E)
131
46.1k
      CurrSet = &Dst;
132
1.46k
    else {
133
1.46k
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp20
: &Tmp1;
134
1.46k
      CurrSet->clear();
135
1.46k
    }
136
47.6k
137
47.6k
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
47.6k
    for (const auto &NI : *PrevSet)
139
47.6k
      checkCtx.runChecker(*I, B, NI);
140
47.6k
141
47.6k
    // If all the produced transitions are sinks, stop.
142
47.6k
    if (CurrSet->empty())
143
57
      return;
144
47.5k
145
47.5k
    // Update which NodeSet is the current one.
146
47.5k
    PrevSet = CurrSet;
147
47.5k
  }
148
46.2k
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckNewAllocatorContext>((anonymous namespace)::CheckNewAllocatorContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
6.42k
                                    const ExplodedNodeSet &Src) {
114
6.42k
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
6.42k
  if (Src.empty())
116
0
    return;
117
6.42k
118
6.42k
  typename CHECK_CTX::CheckersTy::const_iterator
119
6.42k
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
6.42k
  if (I == E) {
121
5.77k
    Dst.insert(Src);
122
5.77k
    return;
123
5.77k
  }
124
644
125
644
  ExplodedNodeSet Tmp1, Tmp2;
126
644
  const ExplodedNodeSet *PrevSet = &Src;
127
644
128
1.28k
  for (; I != E; 
++I644
) {
129
644
    ExplodedNodeSet *CurrSet = nullptr;
130
644
    if (I+1 == E)
131
644
      CurrSet = &Dst;
132
0
    else {
133
0
      CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
134
0
      CurrSet->clear();
135
0
    }
136
644
137
644
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
644
    for (const auto &NI : *PrevSet)
139
644
      checkCtx.runChecker(*I, B, NI);
140
644
141
644
    // If all the produced transitions are sinks, stop.
142
644
    if (CurrSet->empty())
143
0
      return;
144
644
145
644
    // Update which NodeSet is the current one.
146
644
    PrevSet = CurrSet;
147
644
  }
148
644
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckDeadSymbolsContext>((anonymous namespace)::CheckDeadSymbolsContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
470k
                                    const ExplodedNodeSet &Src) {
114
470k
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
470k
  if (Src.empty())
116
0
    return;
117
470k
118
470k
  typename CHECK_CTX::CheckersTy::const_iterator
119
470k
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
470k
  if (I == E) {
121
3.43k
    Dst.insert(Src);
122
3.43k
    return;
123
3.43k
  }
124
466k
125
466k
  ExplodedNodeSet Tmp1, Tmp2;
126
466k
  const ExplodedNodeSet *PrevSet = &Src;
127
466k
128
1.71M
  for (; I != E; 
++I1.24M
) {
129
1.24M
    ExplodedNodeSet *CurrSet = nullptr;
130
1.24M
    if (I+1 == E)
131
466k
      CurrSet = &Dst;
132
776k
    else {
133
776k
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp2297k
:
&Tmp1479k
;
134
776k
      CurrSet->clear();
135
776k
    }
136
1.24M
137
1.24M
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
1.24M
    for (const auto &NI : *PrevSet)
139
1.24M
      checkCtx.runChecker(*I, B, NI);
140
1.24M
141
1.24M
    // If all the produced transitions are sinks, stop.
142
1.24M
    if (CurrSet->empty())
143
23
      return;
144
1.24M
145
1.24M
    // Update which NodeSet is the current one.
146
1.24M
    PrevSet = CurrSet;
147
1.24M
  }
148
466k
}
149
150
namespace {
151
152
  struct CheckStmtContext {
153
    using CheckersTy = SmallVectorImpl<CheckerManager::CheckStmtFunc>;
154
155
    bool IsPreVisit;
156
    const CheckersTy &Checkers;
157
    const Stmt *S;
158
    ExprEngine &Eng;
159
    bool WasInlined;
160
161
    CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
162
                     const Stmt *s, ExprEngine &eng, bool wasInlined = false)
163
        : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng),
164
1.76M
          WasInlined(wasInlined) {}
165
166
1.70M
    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
167
1.70M
    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
168
169
    void runChecker(CheckerManager::CheckStmtFunc checkFn,
170
1.15M
                    NodeBuilder &Bldr, ExplodedNode *Pred) {
171
1.15M
      // FIXME: Remove respondsToCallback from CheckerContext;
172
1.15M
      ProgramPoint::Kind K =  IsPreVisit ? 
ProgramPoint::PreStmtKind494k
:
173
1.15M
                                           
ProgramPoint::PostStmtKind661k
;
174
1.15M
      const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
175
1.15M
                                Pred->getLocationContext(), checkFn.Checker);
176
1.15M
      CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
177
1.15M
      checkFn(S, C);
178
1.15M
    }
179
  };
180
181
} // namespace
182
183
/// Run checkers for visiting Stmts.
184
void CheckerManager::runCheckersForStmt(bool isPreVisit,
185
                                        ExplodedNodeSet &Dst,
186
                                        const ExplodedNodeSet &Src,
187
                                        const Stmt *S,
188
                                        ExprEngine &Eng,
189
1.76M
                                        bool WasInlined) {
190
1.76M
  CheckStmtContext C(isPreVisit, getCachedStmtCheckersFor(S, isPreVisit),
191
1.76M
                     S, Eng, WasInlined);
192
1.76M
  expandGraphWithCheckers(C, Dst, Src);
193
1.76M
}
194
195
namespace {
196
197
  struct CheckObjCMessageContext {
198
    using CheckersTy = std::vector<CheckerManager::CheckObjCMessageFunc>;
199
200
    ObjCMessageVisitKind Kind;
201
    bool WasInlined;
202
    const CheckersTy &Checkers;
203
    const ObjCMethodCall &Msg;
204
    ExprEngine &Eng;
205
206
    CheckObjCMessageContext(ObjCMessageVisitKind visitKind,
207
                            const CheckersTy &checkers,
208
                            const ObjCMethodCall &msg, ExprEngine &eng,
209
                            bool wasInlined)
210
        : Kind(visitKind), WasInlined(wasInlined), Checkers(checkers), Msg(msg),
211
8.73k
          Eng(eng) {}
212
213
8.07k
    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
214
8.07k
    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
215
216
    void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
217
17.9k
                    NodeBuilder &Bldr, ExplodedNode *Pred) {
218
17.9k
      bool IsPreVisit;
219
17.9k
220
17.9k
      switch (Kind) {
221
9.53k
        case ObjCMessageVisitKind::Pre:
222
9.53k
          IsPreVisit = true;
223
9.53k
          break;
224
8.40k
        case ObjCMessageVisitKind::MessageNil:
225
8.40k
        case ObjCMessageVisitKind::Post:
226
8.40k
          IsPreVisit = false;
227
8.40k
          break;
228
17.9k
      }
229
17.9k
230
17.9k
      const ProgramPoint &L = Msg.getProgramPoint(IsPreVisit,checkFn.Checker);
231
17.9k
      CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
232
17.9k
233
17.9k
      checkFn(*Msg.cloneWithState<ObjCMethodCall>(Pred->getState()), C);
234
17.9k
    }
235
  };
236
237
} // namespace
238
239
/// Run checkers for visiting obj-c messages.
240
void CheckerManager::runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,
241
                                               ExplodedNodeSet &Dst,
242
                                               const ExplodedNodeSet &Src,
243
                                               const ObjCMethodCall &msg,
244
                                               ExprEngine &Eng,
245
8.73k
                                               bool WasInlined) {
246
8.73k
  auto &checkers = getObjCMessageCheckers(visitKind);
247
8.73k
  CheckObjCMessageContext C(visitKind, checkers, msg, Eng, WasInlined);
248
8.73k
  expandGraphWithCheckers(C, Dst, Src);
249
8.73k
}
250
251
const std::vector<CheckerManager::CheckObjCMessageFunc> &
252
8.73k
CheckerManager::getObjCMessageCheckers(ObjCMessageVisitKind Kind) {
253
8.73k
  switch (Kind) {
254
4.03k
  case ObjCMessageVisitKind::Pre:
255
4.03k
    return PreObjCMessageCheckers;
256
0
    break;
257
4.60k
  case ObjCMessageVisitKind::Post:
258
4.60k
    return PostObjCMessageCheckers;
259
95
  case ObjCMessageVisitKind::MessageNil:
260
95
    return ObjCMessageNilCheckers;
261
0
  }
262
0
  llvm_unreachable("Unknown Kind");
263
0
}
264
265
namespace {
266
267
  // FIXME: This has all the same signatures as CheckObjCMessageContext.
268
  // Is there a way we can merge the two?
269
  struct CheckCallContext {
270
    using CheckersTy = std::vector<CheckerManager::CheckCallFunc>;
271
272
    bool IsPreVisit, WasInlined;
273
    const CheckersTy &Checkers;
274
    const CallEvent &Call;
275
    ExprEngine &Eng;
276
277
    CheckCallContext(bool isPreVisit, const CheckersTy &checkers,
278
                     const CallEvent &call, ExprEngine &eng,
279
                     bool wasInlined)
280
        : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
281
340k
          Call(call), Eng(eng) {}
282
283
274k
    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
284
274k
    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
285
286
    void runChecker(CheckerManager::CheckCallFunc checkFn,
287
983k
                    NodeBuilder &Bldr, ExplodedNode *Pred) {
288
983k
      const ProgramPoint &L = Call.getProgramPoint(IsPreVisit,checkFn.Checker);
289
983k
      CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
290
983k
291
983k
      checkFn(*Call.cloneWithState(Pred->getState()), C);
292
983k
    }
293
  };
294
295
} // namespace
296
297
/// Run checkers for visiting an abstract call event.
298
void CheckerManager::runCheckersForCallEvent(bool isPreVisit,
299
                                             ExplodedNodeSet &Dst,
300
                                             const ExplodedNodeSet &Src,
301
                                             const CallEvent &Call,
302
                                             ExprEngine &Eng,
303
340k
                                             bool WasInlined) {
304
340k
  CheckCallContext C(isPreVisit,
305
340k
                     isPreVisit ? 
PreCallCheckers132k
306
340k
                                : 
PostCallCheckers207k
,
307
340k
                     Call, Eng, WasInlined);
308
340k
  expandGraphWithCheckers(C, Dst, Src);
309
340k
}
310
311
namespace {
312
313
  struct CheckLocationContext {
314
    using CheckersTy = std::vector<CheckerManager::CheckLocationFunc>;
315
316
    const CheckersTy &Checkers;
317
    SVal Loc;
318
    bool IsLoad;
319
    const Stmt *NodeEx; /* Will become a CFGStmt */
320
    const Stmt *BoundEx;
321
    ExprEngine &Eng;
322
323
    CheckLocationContext(const CheckersTy &checkers,
324
                         SVal loc, bool isLoad, const Stmt *NodeEx,
325
                         const Stmt *BoundEx,
326
                         ExprEngine &eng)
327
        : Checkers(checkers), Loc(loc), IsLoad(isLoad), NodeEx(NodeEx),
328
210k
          BoundEx(BoundEx), Eng(eng) {}
329
330
210k
    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
331
210k
    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
332
333
    void runChecker(CheckerManager::CheckLocationFunc checkFn,
334
503k
                    NodeBuilder &Bldr, ExplodedNode *Pred) {
335
503k
      ProgramPoint::Kind K =  IsLoad ? 
ProgramPoint::PreLoadKind427k
:
336
503k
                                       
ProgramPoint::PreStoreKind76.1k
;
337
503k
      const ProgramPoint &L =
338
503k
        ProgramPoint::getProgramPoint(NodeEx, K,
339
503k
                                      Pred->getLocationContext(),
340
503k
                                      checkFn.Checker);
341
503k
      CheckerContext C(Bldr, Eng, Pred, L);
342
503k
      checkFn(Loc, IsLoad, BoundEx, C);
343
503k
    }
344
  };
345
346
} // namespace
347
348
/// Run checkers for load/store of a location.
349
350
void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
351
                                            const ExplodedNodeSet &Src,
352
                                            SVal location, bool isLoad,
353
                                            const Stmt *NodeEx,
354
                                            const Stmt *BoundEx,
355
210k
                                            ExprEngine &Eng) {
356
210k
  CheckLocationContext C(LocationCheckers, location, isLoad, NodeEx,
357
210k
                         BoundEx, Eng);
358
210k
  expandGraphWithCheckers(C, Dst, Src);
359
210k
}
360
361
namespace {
362
363
  struct CheckBindContext {
364
    using CheckersTy = std::vector<CheckerManager::CheckBindFunc>;
365
366
    const CheckersTy &Checkers;
367
    SVal Loc;
368
    SVal Val;
369
    const Stmt *S;
370
    ExprEngine &Eng;
371
    const ProgramPoint &PP;
372
373
    CheckBindContext(const CheckersTy &checkers,
374
                     SVal loc, SVal val, const Stmt *s, ExprEngine &eng,
375
                     const ProgramPoint &pp)
376
83.6k
        : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PP(pp) {}
377
378
83.6k
    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
379
83.6k
    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
380
381
    void runChecker(CheckerManager::CheckBindFunc checkFn,
382
170k
                    NodeBuilder &Bldr, ExplodedNode *Pred) {
383
170k
      const ProgramPoint &L = PP.withTag(checkFn.Checker);
384
170k
      CheckerContext C(Bldr, Eng, Pred, L);
385
170k
386
170k
      checkFn(Loc, Val, S, C);
387
170k
    }
388
  };
389
390
} // namespace
391
392
/// Run checkers for binding of a value to a location.
393
void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst,
394
                                        const ExplodedNodeSet &Src,
395
                                        SVal location, SVal val,
396
                                        const Stmt *S, ExprEngine &Eng,
397
83.6k
                                        const ProgramPoint &PP) {
398
83.6k
  CheckBindContext C(BindCheckers, location, val, S, Eng, PP);
399
83.6k
  expandGraphWithCheckers(C, Dst, Src);
400
83.6k
}
401
402
void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
403
                                               BugReporter &BR,
404
12.6k
                                               ExprEngine &Eng) {
405
12.6k
  for (const auto &EndAnalysisChecker : EndAnalysisCheckers)
406
6.65k
    EndAnalysisChecker(G, BR, Eng);
407
12.6k
}
408
409
namespace {
410
411
struct CheckBeginFunctionContext {
412
  using CheckersTy = std::vector<CheckerManager::CheckBeginFunctionFunc>;
413
414
  const CheckersTy &Checkers;
415
  ExprEngine &Eng;
416
  const ProgramPoint &PP;
417
418
  CheckBeginFunctionContext(const CheckersTy &Checkers, ExprEngine &Eng,
419
                            const ProgramPoint &PP)
420
76.3k
      : Checkers(Checkers), Eng(Eng), PP(PP) {}
421
422
76.3k
  CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
423
76.3k
  CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
424
425
  void runChecker(CheckerManager::CheckBeginFunctionFunc checkFn,
426
14.0k
                  NodeBuilder &Bldr, ExplodedNode *Pred) {
427
14.0k
    const ProgramPoint &L = PP.withTag(checkFn.Checker);
428
14.0k
    CheckerContext C(Bldr, Eng, Pred, L);
429
14.0k
430
14.0k
    checkFn(C);
431
14.0k
  }
432
};
433
434
} // namespace
435
436
void CheckerManager::runCheckersForBeginFunction(ExplodedNodeSet &Dst,
437
                                                 const BlockEdge &L,
438
                                                 ExplodedNode *Pred,
439
76.3k
                                                 ExprEngine &Eng) {
440
76.3k
  ExplodedNodeSet Src;
441
76.3k
  Src.insert(Pred);
442
76.3k
  CheckBeginFunctionContext C(BeginFunctionCheckers, Eng, L);
443
76.3k
  expandGraphWithCheckers(C, Dst, Src);
444
76.3k
}
445
446
/// Run checkers for end of path.
447
// Note, We do not chain the checker output (like in expandGraphWithCheckers)
448
// for this callback since end of path nodes are expected to be final.
449
void CheckerManager::runCheckersForEndFunction(NodeBuilderContext &BC,
450
                                               ExplodedNodeSet &Dst,
451
                                               ExplodedNode *Pred,
452
                                               ExprEngine &Eng,
453
98.9k
                                               const ReturnStmt *RS) {
454
98.9k
  // We define the builder outside of the loop because if at least one checker
455
98.9k
  // creates a successor for Pred, we do not need to generate an
456
98.9k
  // autotransition for it.
457
98.9k
  NodeBuilder Bldr(Pred, Dst, BC);
458
135k
  for (const auto &checkFn : EndFunctionCheckers) {
459
135k
    const ProgramPoint &L =
460
135k
        FunctionExitPoint(RS, Pred->getLocationContext(), checkFn.Checker);
461
135k
    CheckerContext C(Bldr, Eng, Pred, L);
462
135k
    checkFn(RS, C);
463
135k
  }
464
98.9k
}
465
466
namespace {
467
468
  struct CheckBranchConditionContext {
469
    using CheckersTy = std::vector<CheckerManager::CheckBranchConditionFunc>;
470
471
    const CheckersTy &Checkers;
472
    const Stmt *Condition;
473
    ExprEngine &Eng;
474
475
    CheckBranchConditionContext(const CheckersTy &checkers,
476
                                const Stmt *Cond, ExprEngine &eng)
477
47.2k
        : Checkers(checkers), Condition(Cond), Eng(eng) {}
478
479
47.2k
    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
480
47.2k
    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
481
482
    void runChecker(CheckerManager::CheckBranchConditionFunc checkFn,
483
47.6k
                    NodeBuilder &Bldr, ExplodedNode *Pred) {
484
47.6k
      ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(),
485
47.6k
                                     checkFn.Checker);
486
47.6k
      CheckerContext C(Bldr, Eng, Pred, L);
487
47.6k
      checkFn(Condition, C);
488
47.6k
    }
489
  };
490
491
} // namespace
492
493
/// Run checkers for branch condition.
494
void CheckerManager::runCheckersForBranchCondition(const Stmt *Condition,
495
                                                   ExplodedNodeSet &Dst,
496
                                                   ExplodedNode *Pred,
497
47.2k
                                                   ExprEngine &Eng) {
498
47.2k
  ExplodedNodeSet Src;
499
47.2k
  Src.insert(Pred);
500
47.2k
  CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng);
501
47.2k
  expandGraphWithCheckers(C, Dst, Src);
502
47.2k
}
503
504
namespace {
505
506
  struct CheckNewAllocatorContext {
507
    using CheckersTy = std::vector<CheckerManager::CheckNewAllocatorFunc>;
508
509
    const CheckersTy &Checkers;
510
    const CXXNewExpr *NE;
511
    SVal Target;
512
    bool WasInlined;
513
    ExprEngine &Eng;
514
515
    CheckNewAllocatorContext(const CheckersTy &Checkers, const CXXNewExpr *NE,
516
                             SVal Target, bool WasInlined, ExprEngine &Eng)
517
        : Checkers(Checkers), NE(NE), Target(Target), WasInlined(WasInlined),
518
6.42k
          Eng(Eng) {}
519
520
6.42k
    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
521
6.42k
    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
522
523
    void runChecker(CheckerManager::CheckNewAllocatorFunc checkFn,
524
644
                    NodeBuilder &Bldr, ExplodedNode *Pred) {
525
644
      ProgramPoint L = PostAllocatorCall(NE, Pred->getLocationContext());
526
644
      CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
527
644
      checkFn(NE, Target, C);
528
644
    }
529
  };
530
531
} // namespace
532
533
void CheckerManager::runCheckersForNewAllocator(
534
    const CXXNewExpr *NE, SVal Target, ExplodedNodeSet &Dst, ExplodedNode *Pred,
535
6.42k
    ExprEngine &Eng, bool WasInlined) {
536
6.42k
  ExplodedNodeSet Src;
537
6.42k
  Src.insert(Pred);
538
6.42k
  CheckNewAllocatorContext C(NewAllocatorCheckers, NE, Target, WasInlined, Eng);
539
6.42k
  expandGraphWithCheckers(C, Dst, Src);
540
6.42k
}
541
542
/// Run checkers for live symbols.
543
void CheckerManager::runCheckersForLiveSymbols(ProgramStateRef state,
544
470k
                                               SymbolReaper &SymReaper) {
545
470k
  for (const auto &LiveSymbolsChecker : LiveSymbolsCheckers)
546
153k
    LiveSymbolsChecker(state, SymReaper);
547
470k
}
548
549
namespace {
550
551
  struct CheckDeadSymbolsContext {
552
    using CheckersTy = std::vector<CheckerManager::CheckDeadSymbolsFunc>;
553
554
    const CheckersTy &Checkers;
555
    SymbolReaper &SR;
556
    const Stmt *S;
557
    ExprEngine &Eng;
558
    ProgramPoint::Kind ProgarmPointKind;
559
560
    CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
561
                            const Stmt *s, ExprEngine &eng,
562
                            ProgramPoint::Kind K)
563
470k
        : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgarmPointKind(K) {}
564
565
470k
    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
566
470k
    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
567
568
    void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
569
1.24M
                    NodeBuilder &Bldr, ExplodedNode *Pred) {
570
1.24M
      const ProgramPoint &L = ProgramPoint::getProgramPoint(S, ProgarmPointKind,
571
1.24M
                                Pred->getLocationContext(), checkFn.Checker);
572
1.24M
      CheckerContext C(Bldr, Eng, Pred, L);
573
1.24M
574
1.24M
      // Note, do not pass the statement to the checkers without letting them
575
1.24M
      // differentiate if we ran remove dead bindings before or after the
576
1.24M
      // statement.
577
1.24M
      checkFn(SR, C);
578
1.24M
    }
579
  };
580
581
} // namespace
582
583
/// Run checkers for dead symbols.
584
void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
585
                                               const ExplodedNodeSet &Src,
586
                                               SymbolReaper &SymReaper,
587
                                               const Stmt *S,
588
                                               ExprEngine &Eng,
589
470k
                                               ProgramPoint::Kind K) {
590
470k
  CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng, K);
591
470k
  expandGraphWithCheckers(C, Dst, Src);
592
470k
}
593
594
/// Run checkers for region changes.
595
ProgramStateRef
596
CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
597
                                            const InvalidatedSymbols *invalidated,
598
                                            ArrayRef<const MemRegion *> ExplicitRegions,
599
                                            ArrayRef<const MemRegion *> Regions,
600
                                            const LocationContext *LCtx,
601
152k
                                            const CallEvent *Call) {
602
152k
  for (const auto &RegionChangesChecker : RegionChangesCheckers) {
603
107k
    // If any checker declares the state infeasible (or if it starts that way),
604
107k
    // bail out.
605
107k
    if (!state)
606
0
      return nullptr;
607
107k
    state = RegionChangesChecker(state, invalidated, ExplicitRegions, Regions,
608
107k
                                 LCtx, Call);
609
107k
  }
610
152k
  return state;
611
152k
}
612
613
/// Run checkers to process symbol escape event.
614
ProgramStateRef
615
CheckerManager::runCheckersForPointerEscape(ProgramStateRef State,
616
                                   const InvalidatedSymbols &Escaped,
617
                                   const CallEvent *Call,
618
                                   PointerEscapeKind Kind,
619
41.1k
                                   RegionAndSymbolInvalidationTraits *ETraits) {
620
41.1k
  assert((Call != nullptr ||
621
41.1k
          (Kind != PSK_DirectEscapeOnCall &&
622
41.1k
           Kind != PSK_IndirectEscapeOnCall)) &&
623
41.1k
         "Call must not be NULL when escaping on call");
624
41.1k
  for (const auto &PointerEscapeChecker : PointerEscapeCheckers) {
625
30.5k
    // If any checker declares the state infeasible (or if it starts that
626
30.5k
    //  way), bail out.
627
30.5k
    if (!State)
628
0
      return nullptr;
629
30.5k
    State = PointerEscapeChecker(State, Escaped, Call, Kind, ETraits);
630
30.5k
  }
631
41.1k
  return State;
632
41.1k
}
633
634
/// Run checkers for handling assumptions on symbolic values.
635
ProgramStateRef
636
CheckerManager::runCheckersForEvalAssume(ProgramStateRef state,
637
887k
                                         SVal Cond, bool Assumption) {
638
887k
  for (const auto &EvalAssumeChecker : EvalAssumeCheckers) {
639
349k
    // If any checker declares the state infeasible (or if it starts that way),
640
349k
    // bail out.
641
349k
    if (!state)
642
154k
      return nullptr;
643
195k
    state = EvalAssumeChecker(state, Cond, Assumption);
644
195k
  }
645
887k
  
return state733k
;
646
887k
}
647
648
/// Run checkers for evaluating a call.
649
/// Only one checker will evaluate the call.
650
void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
651
                                            const ExplodedNodeSet &Src,
652
                                            const CallEvent &Call,
653
82.1k
                                            ExprEngine &Eng) {
654
82.1k
  for (const auto Pred : Src) {
655
81.6k
    bool anyEvaluated = false;
656
81.6k
657
81.6k
    ExplodedNodeSet checkDst;
658
81.6k
    NodeBuilder B(Pred, checkDst, Eng.getBuilderContext());
659
81.6k
660
81.6k
    // Check if any of the EvalCall callbacks can evaluate the call.
661
179k
    for (const auto &EvalCallChecker : EvalCallCheckers) {
662
179k
      // TODO: Support the situation when the call doesn't correspond
663
179k
      // to any Expr.
664
179k
      ProgramPoint L = ProgramPoint::getProgramPoint(
665
179k
          cast<CallExpr>(Call.getOriginExpr()),
666
179k
          ProgramPoint::PostStmtKind,
667
179k
          Pred->getLocationContext(),
668
179k
          EvalCallChecker.Checker);
669
179k
      bool evaluated = false;
670
179k
      { // CheckerContext generates transitions(populates checkDest) on
671
179k
        // destruction, so introduce the scope to make sure it gets properly
672
179k
        // populated.
673
179k
        CheckerContext C(B, Eng, Pred, L);
674
179k
        evaluated = EvalCallChecker(Call, C);
675
179k
      }
676
179k
      assert(!(evaluated && anyEvaluated)
677
179k
             && "There are more than one checkers evaluating the call");
678
179k
      if (evaluated) {
679
14.7k
        anyEvaluated = true;
680
14.7k
        Dst.insert(checkDst);
681
#ifdef NDEBUG
682
        break; // on release don't check that no other checker also evals.
683
#endif
684
      }
685
179k
    }
686
81.6k
687
81.6k
    // If none of the checkers evaluated the call, ask ExprEngine to handle it.
688
81.6k
    if (!anyEvaluated) {
689
66.9k
      NodeBuilder B(Pred, Dst, Eng.getBuilderContext());
690
66.9k
      Eng.defaultEvalCall(B, Pred, Call);
691
66.9k
    }
692
81.6k
  }
693
82.1k
}
694
695
/// Run checkers for the entire Translation Unit.
696
void CheckerManager::runCheckersOnEndOfTranslationUnit(
697
                                                  const TranslationUnitDecl *TU,
698
                                                  AnalysisManager &mgr,
699
1.22k
                                                  BugReporter &BR) {
700
1.22k
  for (const auto &EndOfTranslationUnitChecker : EndOfTranslationUnitCheckers)
701
31
    EndOfTranslationUnitChecker(TU, mgr, BR);
702
1.22k
}
703
704
void CheckerManager::runCheckersForPrintStateJson(raw_ostream &Out,
705
                                                  ProgramStateRef State,
706
                                                  const char *NL,
707
                                                  unsigned int Space,
708
107
                                                  bool IsDot) const {
709
107
  Indent(Out, Space, IsDot) << "\"checker_messages\": ";
710
107
711
107
  // Create a temporary stream to see whether we have any message.
712
107
  SmallString<1024> TempBuf;
713
107
  llvm::raw_svector_ostream TempOut(TempBuf);
714
107
  unsigned int InnerSpace = Space + 2;
715
107
716
107
  // Create the new-line in JSON with enough space.
717
107
  SmallString<128> NewLine;
718
107
  llvm::raw_svector_ostream NLOut(NewLine);
719
107
  NLOut << "\", " << NL;                     // Inject the ending and a new line
720
107
  Indent(NLOut, InnerSpace, IsDot) << "\"";  // then begin the next message.
721
107
722
107
  ++Space;
723
107
  bool HasMessage = false;
724
107
725
107
  // Store the last CheckerTag.
726
107
  const void *LastCT = nullptr;
727
1.84k
  for (const auto &CT : CheckerTags) {
728
1.84k
    // See whether the current checker has a message.
729
1.84k
    CT.second->printState(TempOut, State, /*NL=*/NewLine.c_str(), /*Sep=*/"");
730
1.84k
731
1.84k
    if (TempBuf.empty())
732
1.82k
      continue;
733
23
734
23
    if (!HasMessage) {
735
15
      Out << '[' << NL;
736
15
      HasMessage = true;
737
15
    }
738
23
739
23
    LastCT = &CT;
740
23
    TempBuf.clear();
741
23
  }
742
107
743
1.84k
  for (const auto &CT : CheckerTags) {
744
1.84k
    // See whether the current checker has a message.
745
1.84k
    CT.second->printState(TempOut, State, /*NL=*/NewLine.c_str(), /*Sep=*/"");
746
1.84k
747
1.84k
    if (TempBuf.empty())
748
1.82k
      continue;
749
23
750
23
    Indent(Out, Space, IsDot)
751
23
        << "{ \"checker\": \"" << CT.second->getCheckerName().getName()
752
23
        << "\", \"messages\": [" << NL;
753
23
    Indent(Out, InnerSpace, IsDot)
754
23
        << '\"' << TempBuf.str().trim() << '\"' << NL;
755
23
    Indent(Out, Space, IsDot) << "]}";
756
23
757
23
    if (&CT != LastCT)
758
8
      Out << ',';
759
23
    Out << NL;
760
23
761
23
    TempBuf.clear();
762
23
  }
763
107
764
107
  // It is the last element of the 'program_state' so do not add a comma.
765
107
  if (HasMessage)
766
15
    Indent(Out, --Space, IsDot) << "]";
767
92
  else
768
92
    Out << "null";
769
107
770
107
  Out << NL;
771
107
}
772
773
//===----------------------------------------------------------------------===//
774
// Internal registration functions for AST traversing.
775
//===----------------------------------------------------------------------===//
776
777
void CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
778
253
                                      HandlesDeclFunc isForDeclFn) {
779
253
  DeclCheckerInfo info = { checkfn, isForDeclFn };
780
253
  DeclCheckers.push_back(info);
781
253
}
782
783
632
void CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
784
632
  BodyCheckers.push_back(checkfn);
785
632
}
786
787
//===----------------------------------------------------------------------===//
788
// Internal registration functions for path-sensitive checking.
789
//===----------------------------------------------------------------------===//
790
791
void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
792
8.80k
                                         HandlesStmtFunc isForStmtFn) {
793
8.80k
  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
794
8.80k
  StmtCheckers.push_back(info);
795
8.80k
}
796
797
void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
798
5.83k
                                          HandlesStmtFunc isForStmtFn) {
799
5.83k
  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
800
5.83k
  StmtCheckers.push_back(info);
801
5.83k
}
802
803
2.19k
void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
804
2.19k
  PreObjCMessageCheckers.push_back(checkfn);
805
2.19k
}
806
807
1.00k
void CheckerManager::_registerForObjCMessageNil(CheckObjCMessageFunc checkfn) {
808
1.00k
  ObjCMessageNilCheckers.push_back(checkfn);
809
1.00k
}
810
811
2.45k
void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
812
2.45k
  PostObjCMessageCheckers.push_back(checkfn);
813
2.45k
}
814
815
4.61k
void CheckerManager::_registerForPreCall(CheckCallFunc checkfn) {
816
4.61k
  PreCallCheckers.push_back(checkfn);
817
4.61k
}
818
2.57k
void CheckerManager::_registerForPostCall(CheckCallFunc checkfn) {
819
2.57k
  PostCallCheckers.push_back(checkfn);
820
2.57k
}
821
822
2.34k
void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
823
2.34k
  LocationCheckers.push_back(checkfn);
824
2.34k
}
825
826
2.30k
void CheckerManager::_registerForBind(CheckBindFunc checkfn) {
827
2.30k
  BindCheckers.push_back(checkfn);
828
2.30k
}
829
830
283
void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
831
283
  EndAnalysisCheckers.push_back(checkfn);
832
283
}
833
834
234
void CheckerManager::_registerForBeginFunction(CheckBeginFunctionFunc checkfn) {
835
234
  BeginFunctionCheckers.push_back(checkfn);
836
234
}
837
838
1.53k
void CheckerManager::_registerForEndFunction(CheckEndFunctionFunc checkfn) {
839
1.53k
  EndFunctionCheckers.push_back(checkfn);
840
1.53k
}
841
842
void CheckerManager::_registerForBranchCondition(
843
1.08k
                                             CheckBranchConditionFunc checkfn) {
844
1.08k
  BranchConditionCheckers.push_back(checkfn);
845
1.08k
}
846
847
215
void CheckerManager::_registerForNewAllocator(CheckNewAllocatorFunc checkfn) {
848
215
  NewAllocatorCheckers.push_back(checkfn);
849
215
}
850
851
274
void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) {
852
274
  LiveSymbolsCheckers.push_back(checkfn);
853
274
}
854
855
2.24k
void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) {
856
2.24k
  DeadSymbolsCheckers.push_back(checkfn);
857
2.24k
}
858
859
452
void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn) {
860
452
  RegionChangesCheckers.push_back(checkfn);
861
452
}
862
863
565
void CheckerManager::_registerForPointerEscape(CheckPointerEscapeFunc checkfn){
864
565
  PointerEscapeCheckers.push_back(checkfn);
865
565
}
866
867
void CheckerManager::_registerForConstPointerEscape(
868
0
                                          CheckPointerEscapeFunc checkfn) {
869
0
  PointerEscapeCheckers.push_back(checkfn);
870
0
}
871
872
377
void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) {
873
377
  EvalAssumeCheckers.push_back(checkfn);
874
377
}
875
876
1.74k
void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
877
1.74k
  EvalCallCheckers.push_back(checkfn);
878
1.74k
}
879
880
void CheckerManager::_registerForEndOfTranslationUnit(
881
31
                                            CheckEndOfTranslationUnit checkfn) {
882
31
  EndOfTranslationUnitCheckers.push_back(checkfn);
883
31
}
884
885
//===----------------------------------------------------------------------===//
886
// Implementation details.
887
//===----------------------------------------------------------------------===//
888
889
const CheckerManager::CachedStmtCheckers &
890
1.76M
CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
891
1.76M
  assert(S);
892
1.76M
893
1.76M
  unsigned Key = (S->getStmtClass() << 1) | unsigned(isPreVisit);
894
1.76M
  CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(Key);
895
1.76M
  if (CCI != CachedStmtCheckersMap.end())
896
1.74M
    return CCI->second;
897
18.9k
898
18.9k
  // Find the checkers that should run for this Stmt and cache them.
899
18.9k
  CachedStmtCheckers &Checkers = CachedStmtCheckersMap[Key];
900
18.9k
  for (const auto &Info : StmtCheckers)
901
250k
    if (Info.IsPreVisit == isPreVisit && 
Info.IsForStmtFn(S)125k
)
902
8.22k
      Checkers.push_back(Info.CheckFn);
903
18.9k
  return Checkers;
904
18.9k
}
905
906
1.25k
CheckerManager::~CheckerManager() {
907
1.25k
  for (const auto &CheckerDtor : CheckerDtors)
908
19.6k
    CheckerDtor();
909
1.25k
}