Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/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
12.1k
bool CheckerManager::hasPathSensitiveCheckers() const {
36
12.1k
  return !StmtCheckers.empty()              ||
37
12.1k
         
!PreObjCMessageCheckers.empty()1.61k
||
38
12.1k
         
!PostObjCMessageCheckers.empty()1.61k
||
39
12.1k
         
!PreCallCheckers.empty()1.47k
||
40
12.1k
         
!PostCallCheckers.empty()1.41k
||
41
12.1k
         
!LocationCheckers.empty()1.30k
||
42
12.1k
         
!BindCheckers.empty()1.28k
||
43
12.1k
         
!EndAnalysisCheckers.empty()1.28k
||
44
12.1k
         
!EndFunctionCheckers.empty()1.24k
||
45
12.1k
         
!BranchConditionCheckers.empty()1.24k
||
46
12.1k
         
!LiveSymbolsCheckers.empty()1.24k
||
47
12.1k
         
!DeadSymbolsCheckers.empty()1.24k
||
48
12.1k
         
!RegionChangesCheckers.empty()1.23k
||
49
12.1k
         
!EvalAssumeCheckers.empty()1.23k
||
50
12.1k
         
!EvalCallCheckers.empty()1.23k
;
51
12.1k
}
52
53
910
void CheckerManager::finishedCheckerRegistration() {
54
#ifndef NDEBUG
55
  // Make sure that for every event that has listeners, there is at least
56
  // one dispatcher registered for it.
57
  for (const auto &Event : Events)
58
    assert(Event.second.HasDispatcher &&
59
           "No dispatcher registered for an event");
60
#endif
61
}
62
63
void CheckerManager::reportInvalidCheckerOptionValue(
64
3
    const CheckerBase *C, StringRef OptionName, StringRef ExpectedValueDesc) {
65
3
66
3
  Context.getDiagnostics()
67
3
      .Report(diag::err_analyzer_checker_option_invalid_input)
68
3
          << (llvm::Twine() + C->getTagDescription() + ":" + OptionName).str()
69
3
          << ExpectedValueDesc;
70
3
}
71
72
//===----------------------------------------------------------------------===//
73
// Functions for running checkers for AST traversing..
74
//===----------------------------------------------------------------------===//
75
76
void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
77
66.8k
                                          BugReporter &BR) {
78
66.8k
  assert(D);
79
66.8k
80
66.8k
  unsigned DeclKind = D->getKind();
81
66.8k
  CachedDeclCheckers *checkers = nullptr;
82
66.8k
  CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
83
66.8k
  if (CCI != CachedDeclCheckersMap.end()) {
84
60.2k
    checkers = &(CCI->second);
85
60.2k
  } else {
86
6.55k
    // Find the checkers that should run for this Decl and cache them.
87
6.55k
    checkers = &CachedDeclCheckersMap[DeclKind];
88
6.55k
    for (const auto &info : DeclCheckers)
89
1.26k
      if (info.IsForDeclFn(D))
90
80
        checkers->push_back(info.CheckFn);
91
6.55k
  }
92
66.8k
93
66.8k
  assert(checkers);
94
66.8k
  for (const auto checker : *checkers)
95
630
    checker(D, mgr, BR);
96
66.8k
}
97
98
void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
99
14.8k
                                          BugReporter &BR) {
100
14.8k
  assert(D && D->hasBody());
101
14.8k
102
14.8k
  for (const auto BodyChecker : BodyCheckers)
103
7.47k
    BodyChecker(D, mgr, BR);
104
14.8k
}
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
2.17M
                                    const ExplodedNodeSet &Src) {
114
2.17M
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
2.17M
  if (Src.empty())
116
64.2k
    return;
117
2.11M
118
2.11M
  typename CHECK_CTX::CheckersTy::const_iterator
119
2.11M
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
2.11M
  if (I == E) {
121
610k
    Dst.insert(Src);
122
610k
    return;
123
610k
  }
124
1.49M
125
1.49M
  ExplodedNodeSet Tmp1, Tmp2;
126
1.49M
  const ExplodedNodeSet *PrevSet = &Src;
127
1.49M
128
4.72M
  for (; I != E; 
++I3.22M
) {
129
3.22M
    ExplodedNodeSet *CurrSet = nullptr;
130
3.22M
    if (I+1 == E)
131
1.49M
      CurrSet = &Dst;
132
1.72M
    else {
133
1.72M
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp2544k
:
&Tmp11.18M
;
134
1.72M
      CurrSet->clear();
135
1.72M
    }
136
3.22M
137
3.22M
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
3.22M
    for (const auto &NI : *PrevSet)
139
3.22M
      checkCtx.runChecker(*I, B, NI);
140
3.22M
141
3.22M
    // If all the produced transitions are sinks, stop.
142
3.22M
    if (CurrSet->empty())
143
3.05k
      return;
144
3.22M
145
3.22M
    // Update which NodeSet is the current one.
146
3.22M
    PrevSet = CurrSet;
147
3.22M
  }
148
1.49M
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckStmtContext>((anonymous namespace)::CheckStmtContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
1.31M
                                    const ExplodedNodeSet &Src) {
114
1.31M
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
1.31M
  if (Src.empty())
116
31.9k
    return;
117
1.28M
118
1.28M
  typename CHECK_CTX::CheckersTy::const_iterator
119
1.28M
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
1.28M
  if (I == E) {
121
559k
    Dst.insert(Src);
122
559k
    return;
123
559k
  }
124
725k
125
725k
  ExplodedNodeSet Tmp1, Tmp2;
126
725k
  const ExplodedNodeSet *PrevSet = &Src;
127
725k
128
1.72M
  for (; I != E; 
++I995k
) {
129
996k
    ExplodedNodeSet *CurrSet = nullptr;
130
996k
    if (I+1 == E)
131
724k
      CurrSet = &Dst;
132
271k
    else {
133
271k
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp225.3k
:
&Tmp1245k
;
134
271k
      CurrSet->clear();
135
271k
    }
136
996k
137
996k
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
996k
    for (const auto &NI : *PrevSet)
139
996k
      checkCtx.runChecker(*I, B, NI);
140
996k
141
996k
    // If all the produced transitions are sinks, stop.
142
996k
    if (CurrSet->empty())
143
745
      return;
144
995k
145
995k
    // Update which NodeSet is the current one.
146
995k
    PrevSet = CurrSet;
147
995k
  }
148
725k
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckObjCMessageContext>((anonymous namespace)::CheckObjCMessageContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
8.57k
                                    const ExplodedNodeSet &Src) {
114
8.57k
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
8.57k
  if (Src.empty())
116
623
    return;
117
7.95k
118
7.95k
  typename CHECK_CTX::CheckersTy::const_iterator
119
7.95k
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
7.95k
  if (I == E) {
121
110
    Dst.insert(Src);
122
110
    return;
123
110
  }
124
7.84k
125
7.84k
  ExplodedNodeSet Tmp1, Tmp2;
126
7.84k
  const ExplodedNodeSet *PrevSet = &Src;
127
7.84k
128
25.3k
  for (; I != E; 
++I17.5k
) {
129
17.6k
    ExplodedNodeSet *CurrSet = nullptr;
130
17.6k
    if (I+1 == E)
131
7.83k
      CurrSet = &Dst;
132
9.79k
    else {
133
9.79k
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp22.89k
:
&Tmp16.90k
;
134
9.79k
      CurrSet->clear();
135
9.79k
    }
136
17.6k
137
17.6k
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
17.6k
    for (const auto &NI : *PrevSet)
139
17.6k
      checkCtx.runChecker(*I, B, NI);
140
17.6k
141
17.6k
    // If all the produced transitions are sinks, stop.
142
17.6k
    if (CurrSet->empty())
143
75
      return;
144
17.5k
145
17.5k
    // Update which NodeSet is the current one.
146
17.5k
    PrevSet = CurrSet;
147
17.5k
  }
148
7.84k
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckCallContext>((anonymous namespace)::CheckCallContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
197k
                                    const ExplodedNodeSet &Src) {
114
197k
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
197k
  if (Src.empty())
116
31.7k
    return;
117
165k
118
165k
  typename CHECK_CTX::CheckersTy::const_iterator
119
165k
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
165k
  if (I == E) {
121
4.76k
    Dst.insert(Src);
122
4.76k
    return;
123
4.76k
  }
124
160k
125
160k
  ExplodedNodeSet Tmp1, Tmp2;
126
160k
  const ExplodedNodeSet *PrevSet = &Src;
127
160k
128
754k
  for (; I != E; 
++I593k
) {
129
594k
    ExplodedNodeSet *CurrSet = nullptr;
130
594k
    if (I+1 == E)
131
160k
      CurrSet = &Dst;
132
433k
    else {
133
433k
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp2167k
:
&Tmp1266k
;
134
433k
      CurrSet->clear();
135
433k
    }
136
594k
137
594k
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
594k
    for (const auto &NI : *PrevSet)
139
594k
      checkCtx.runChecker(*I, B, NI);
140
594k
141
594k
    // If all the produced transitions are sinks, stop.
142
594k
    if (CurrSet->empty())
143
1.15k
      return;
144
593k
145
593k
    // Update which NodeSet is the current one.
146
593k
    PrevSet = CurrSet;
147
593k
  }
148
160k
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckLocationContext>((anonymous namespace)::CheckLocationContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
180k
                                    const ExplodedNodeSet &Src) {
114
180k
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
180k
  if (Src.empty())
116
0
    return;
117
180k
118
180k
  typename CHECK_CTX::CheckersTy::const_iterator
119
180k
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
180k
  if (I == E) {
121
4.21k
    Dst.insert(Src);
122
4.21k
    return;
123
4.21k
  }
124
176k
125
176k
  ExplodedNodeSet Tmp1, Tmp2;
126
176k
  const ExplodedNodeSet *PrevSet = &Src;
127
176k
128
617k
  for (; I != E; 
++I441k
) {
129
442k
    ExplodedNodeSet *CurrSet = nullptr;
130
442k
    if (I+1 == E)
131
176k
      CurrSet = &Dst;
132
266k
    else {
133
266k
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp289.8k
:
&Tmp1176k
;
134
266k
      CurrSet->clear();
135
266k
    }
136
442k
137
442k
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
442k
    for (const auto &NI : *PrevSet)
139
442k
      checkCtx.runChecker(*I, B, NI);
140
442k
141
442k
    // If all the produced transitions are sinks, stop.
142
442k
    if (CurrSet->empty())
143
866
      return;
144
441k
145
441k
    // Update which NodeSet is the current one.
146
441k
    PrevSet = CurrSet;
147
441k
  }
148
176k
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckBindContext>((anonymous namespace)::CheckBindContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
67.2k
                                    const ExplodedNodeSet &Src) {
114
67.2k
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
67.2k
  if (Src.empty())
116
0
    return;
117
67.2k
118
67.2k
  typename CHECK_CTX::CheckersTy::const_iterator
119
67.2k
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
67.2k
  if (I == E) {
121
1.55k
    Dst.insert(Src);
122
1.55k
    return;
123
1.55k
  }
124
65.6k
125
65.6k
  ExplodedNodeSet Tmp1, Tmp2;
126
65.6k
  const ExplodedNodeSet *PrevSet = &Src;
127
65.6k
128
202k
  for (; I != E; 
++I136k
) {
129
136k
    ExplodedNodeSet *CurrSet = nullptr;
130
136k
    if (I+1 == E)
131
65.6k
      CurrSet = &Dst;
132
71.2k
    else {
133
71.2k
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp25.19k
:
&Tmp166.0k
;
134
71.2k
      CurrSet->clear();
135
71.2k
    }
136
136k
137
136k
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
136k
    for (const auto &NI : *PrevSet)
139
136k
      checkCtx.runChecker(*I, B, NI);
140
136k
141
136k
    // If all the produced transitions are sinks, stop.
142
136k
    if (CurrSet->empty())
143
85
      return;
144
136k
145
136k
    // Update which NodeSet is the current one.
146
136k
    PrevSet = CurrSet;
147
136k
  }
148
65.6k
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckBeginFunctionContext>((anonymous namespace)::CheckBeginFunctionContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
41.3k
                                    const ExplodedNodeSet &Src) {
114
41.3k
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
41.3k
  if (Src.empty())
116
0
    return;
117
41.3k
118
41.3k
  typename CHECK_CTX::CheckersTy::const_iterator
119
41.3k
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
41.3k
  if (I == E) {
121
34.4k
    Dst.insert(Src);
122
34.4k
    return;
123
34.4k
  }
124
6.90k
125
6.90k
  ExplodedNodeSet Tmp1, Tmp2;
126
6.90k
  const ExplodedNodeSet *PrevSet = &Src;
127
6.90k
128
14.2k
  for (; I != E; 
++I7.33k
) {
129
7.33k
    ExplodedNodeSet *CurrSet = nullptr;
130
7.33k
    if (I+1 == E)
131
6.90k
      CurrSet = &Dst;
132
433
    else {
133
433
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp24
:
&Tmp1429
;
134
433
      CurrSet->clear();
135
433
    }
136
7.33k
137
7.33k
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
7.33k
    for (const auto &NI : *PrevSet)
139
7.33k
      checkCtx.runChecker(*I, B, NI);
140
7.33k
141
7.33k
    // If all the produced transitions are sinks, stop.
142
7.33k
    if (CurrSet->empty())
143
0
      return;
144
7.33k
145
7.33k
    // Update which NodeSet is the current one.
146
7.33k
    PrevSet = CurrSet;
147
7.33k
  }
148
6.90k
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckBranchConditionContext>((anonymous namespace)::CheckBranchConditionContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
41.3k
                                    const ExplodedNodeSet &Src) {
114
41.3k
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
41.3k
  if (Src.empty())
116
0
    return;
117
41.3k
118
41.3k
  typename CHECK_CTX::CheckersTy::const_iterator
119
41.3k
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
41.3k
  if (I == E) {
121
1.05k
    Dst.insert(Src);
122
1.05k
    return;
123
1.05k
  }
124
40.2k
125
40.2k
  ExplodedNodeSet Tmp1, Tmp2;
126
40.2k
  const ExplodedNodeSet *PrevSet = &Src;
127
40.2k
128
81.9k
  for (; I != E; 
++I41.6k
) {
129
41.7k
    ExplodedNodeSet *CurrSet = nullptr;
130
41.7k
    if (I+1 == E)
131
40.2k
      CurrSet = &Dst;
132
1.46k
    else {
133
1.46k
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp20
: &Tmp1;
134
1.46k
      CurrSet->clear();
135
1.46k
    }
136
41.7k
137
41.7k
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
41.7k
    for (const auto &NI : *PrevSet)
139
41.7k
      checkCtx.runChecker(*I, B, NI);
140
41.7k
141
41.7k
    // If all the produced transitions are sinks, stop.
142
41.7k
    if (CurrSet->empty())
143
56
      return;
144
41.6k
145
41.6k
    // Update which NodeSet is the current one.
146
41.6k
    PrevSet = CurrSet;
147
41.6k
  }
148
40.2k
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckNewAllocatorContext>((anonymous namespace)::CheckNewAllocatorContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
1.03k
                                    const ExplodedNodeSet &Src) {
114
1.03k
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
1.03k
  if (Src.empty())
116
0
    return;
117
1.03k
118
1.03k
  typename CHECK_CTX::CheckersTy::const_iterator
119
1.03k
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
1.03k
  if (I == E) {
121
406
    Dst.insert(Src);
122
406
    return;
123
406
  }
124
624
125
624
  ExplodedNodeSet Tmp1, Tmp2;
126
624
  const ExplodedNodeSet *PrevSet = &Src;
127
624
128
1.24k
  for (; I != E; 
++I624
) {
129
624
    ExplodedNodeSet *CurrSet = nullptr;
130
624
    if (I+1 == E)
131
624
      CurrSet = &Dst;
132
0
    else {
133
0
      CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
134
0
      CurrSet->clear();
135
0
    }
136
624
137
624
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
624
    for (const auto &NI : *PrevSet)
139
624
      checkCtx.runChecker(*I, B, NI);
140
624
141
624
    // If all the produced transitions are sinks, stop.
142
624
    if (CurrSet->empty())
143
0
      return;
144
624
145
624
    // Update which NodeSet is the current one.
146
624
    PrevSet = CurrSet;
147
624
  }
148
624
}
CheckerManager.cpp:void expandGraphWithCheckers<(anonymous namespace)::CheckDeadSymbolsContext>((anonymous namespace)::CheckDeadSymbolsContext, clang::ento::ExplodedNodeSet&, clang::ento::ExplodedNodeSet const&)
Line
Count
Source
113
320k
                                    const ExplodedNodeSet &Src) {
114
320k
  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
115
320k
  if (Src.empty())
116
0
    return;
117
320k
118
320k
  typename CHECK_CTX::CheckersTy::const_iterator
119
320k
      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
120
320k
  if (I == E) {
121
3.82k
    Dst.insert(Src);
122
3.82k
    return;
123
3.82k
  }
124
316k
125
316k
  ExplodedNodeSet Tmp1, Tmp2;
126
316k
  const ExplodedNodeSet *PrevSet = &Src;
127
316k
128
1.30M
  for (; I != E; 
++I991k
) {
129
991k
    ExplodedNodeSet *CurrSet = nullptr;
130
991k
    if (I+1 == E)
131
316k
      CurrSet = &Dst;
132
675k
    else {
133
675k
      CurrSet = (PrevSet == &Tmp1) ? 
&Tmp2253k
:
&Tmp1421k
;
134
675k
      CurrSet->clear();
135
675k
    }
136
991k
137
991k
    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
138
991k
    for (const auto &NI : *PrevSet)
139
991k
      checkCtx.runChecker(*I, B, NI);
140
991k
141
991k
    // If all the produced transitions are sinks, stop.
142
991k
    if (CurrSet->empty())
143
70
      return;
144
991k
145
991k
    // Update which NodeSet is the current one.
146
991k
    PrevSet = CurrSet;
147
991k
  }
148
316k
}
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.31M
          WasInlined(wasInlined) {}
165
166
1.28M
    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
167
1.28M
    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
168
169
    void runChecker(CheckerManager::CheckStmtFunc checkFn,
170
996k
                    NodeBuilder &Bldr, ExplodedNode *Pred) {
171
996k
      // FIXME: Remove respondsToCallback from CheckerContext;
172
996k
      ProgramPoint::Kind K =  IsPreVisit ? 
ProgramPoint::PreStmtKind436k
:
173
996k
                                           
ProgramPoint::PostStmtKind560k
;
174
996k
      const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
175
996k
                                Pred->getLocationContext(), checkFn.Checker);
176
996k
      CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
177
996k
      checkFn(S, C);
178
996k
    }
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.31M
                                        bool WasInlined) {
190
1.31M
  CheckStmtContext C(isPreVisit, getCachedStmtCheckersFor(S, isPreVisit),
191
1.31M
                     S, Eng, WasInlined);
192
1.31M
  expandGraphWithCheckers(C, Dst, Src);
193
1.31M
}
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.57k
          Eng(eng) {}
212
213
7.95k
    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
214
7.95k
    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
215
216
    void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
217
17.6k
                    NodeBuilder &Bldr, ExplodedNode *Pred) {
218
17.6k
      bool IsPreVisit;
219
17.6k
220
17.6k
      switch (Kind) {
221
17.6k
        case ObjCMessageVisitKind::Pre:
222
9.39k
          IsPreVisit = true;
223
9.39k
          break;
224
17.6k
        case ObjCMessageVisitKind::MessageNil:
225
8.23k
        case ObjCMessageVisitKind::Post:
226
8.23k
          IsPreVisit = false;
227
8.23k
          break;
228
17.6k
      }
229
17.6k
230
17.6k
      const ProgramPoint &L = Msg.getProgramPoint(IsPreVisit,checkFn.Checker);
231
17.6k
      CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
232
17.6k
233
17.6k
      checkFn(*Msg.cloneWithState<ObjCMethodCall>(Pred->getState()), C);
234
17.6k
    }
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.57k
                                               bool WasInlined) {
246
8.57k
  auto &checkers = getObjCMessageCheckers(visitKind);
247
8.57k
  CheckObjCMessageContext C(visitKind, checkers, msg, Eng, WasInlined);
248
8.57k
  expandGraphWithCheckers(C, Dst, Src);
249
8.57k
}
250
251
const std::vector<CheckerManager::CheckObjCMessageFunc> &
252
8.57k
CheckerManager::getObjCMessageCheckers(ObjCMessageVisitKind Kind) {
253
8.57k
  switch (Kind) {
254
8.57k
  case ObjCMessageVisitKind::Pre:
255
3.97k
    return PreObjCMessageCheckers;
256
8.57k
    
break0
;
257
8.57k
  case ObjCMessageVisitKind::Post:
258
4.50k
    return PostObjCMessageCheckers;
259
8.57k
  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
197k
          Call(call), Eng(eng) {}
282
283
165k
    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
284
165k
    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
285
286
    void runChecker(CheckerManager::CheckCallFunc checkFn,
287
594k
                    NodeBuilder &Bldr, ExplodedNode *Pred) {
288
594k
      const ProgramPoint &L = Call.getProgramPoint(IsPreVisit,checkFn.Checker);
289
594k
      CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
290
594k
291
594k
      checkFn(*Call.cloneWithState(Pred->getState()), C);
292
594k
    }
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
197k
                                             bool WasInlined) {
304
197k
  CheckCallContext C(isPreVisit,
305
197k
                     isPreVisit ? 
PreCallCheckers80.1k
306
197k
                                : 
PostCallCheckers117k
,
307
197k
                     Call, Eng, WasInlined);
308
197k
  expandGraphWithCheckers(C, Dst, Src);
309
197k
}
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
180k
          BoundEx(BoundEx), Eng(eng) {}
329
330
180k
    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
331
180k
    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
332
333
    void runChecker(CheckerManager::CheckLocationFunc checkFn,
334
442k
                    NodeBuilder &Bldr, ExplodedNode *Pred) {
335
442k
      ProgramPoint::Kind K =  IsLoad ? 
ProgramPoint::PreLoadKind367k
:
336
442k
                                       
ProgramPoint::PreStoreKind74.5k
;
337
442k
      const ProgramPoint &L =
338
442k
        ProgramPoint::getProgramPoint(NodeEx, K,
339
442k
                                      Pred->getLocationContext(),
340
442k
                                      checkFn.Checker);
341
442k
      CheckerContext C(Bldr, Eng, Pred, L);
342
442k
      checkFn(Loc, IsLoad, BoundEx, C);
343
442k
    }
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
180k
                                            ExprEngine &Eng) {
356
180k
  CheckLocationContext C(LocationCheckers, location, isLoad, NodeEx,
357
180k
                         BoundEx, Eng);
358
180k
  expandGraphWithCheckers(C, Dst, Src);
359
180k
}
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
67.2k
        : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PP(pp) {}
377
378
67.2k
    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
379
67.2k
    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
380
381
    void runChecker(CheckerManager::CheckBindFunc checkFn,
382
136k
                    NodeBuilder &Bldr, ExplodedNode *Pred) {
383
136k
      const ProgramPoint &L = PP.withTag(checkFn.Checker);
384
136k
      CheckerContext C(Bldr, Eng, Pred, L);
385
136k
386
136k
      checkFn(Loc, Val, S, C);
387
136k
    }
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
67.2k
                                        const ProgramPoint &PP) {
398
67.2k
  CheckBindContext C(BindCheckers, location, val, S, Eng, PP);
399
67.2k
  expandGraphWithCheckers(C, Dst, Src);
400
67.2k
}
401
402
void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
403
                                               BugReporter &BR,
404
10.8k
                                               ExprEngine &Eng) {
405
10.8k
  for (const auto EndAnalysisChecker : EndAnalysisCheckers)
406
5.71k
    EndAnalysisChecker(G, BR, Eng);
407
10.8k
}
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
41.3k
      : Checkers(Checkers), Eng(Eng), PP(PP) {}
421
422
41.3k
  CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
423
41.3k
  CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
424
425
  void runChecker(CheckerManager::CheckBeginFunctionFunc checkFn,
426
7.33k
                  NodeBuilder &Bldr, ExplodedNode *Pred) {
427
7.33k
    const ProgramPoint &L = PP.withTag(checkFn.Checker);
428
7.33k
    CheckerContext C(Bldr, Eng, Pred, L);
429
7.33k
430
7.33k
    checkFn(C);
431
7.33k
  }
432
};
433
434
} // namespace
435
436
void CheckerManager::runCheckersForBeginFunction(ExplodedNodeSet &Dst,
437
                                                 const BlockEdge &L,
438
                                                 ExplodedNode *Pred,
439
41.3k
                                                 ExprEngine &Eng) {
440
41.3k
  ExplodedNodeSet Src;
441
41.3k
  Src.insert(Pred);
442
41.3k
  CheckBeginFunctionContext C(BeginFunctionCheckers, Eng, L);
443
41.3k
  expandGraphWithCheckers(C, Dst, Src);
444
41.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
56.6k
                                               const ReturnStmt *RS) {
454
56.6k
  // We define the builder outside of the loop because if at least one checker
455
56.6k
  // creates a successor for Pred, we do not need to generate an
456
56.6k
  // autotransition for it.
457
56.6k
  NodeBuilder Bldr(Pred, Dst, BC);
458
79.5k
  for (const auto checkFn : EndFunctionCheckers) {
459
79.5k
    const ProgramPoint &L =
460
79.5k
        FunctionExitPoint(RS, Pred->getLocationContext(), checkFn.Checker);
461
79.5k
    CheckerContext C(Bldr, Eng, Pred, L);
462
79.5k
    checkFn(RS, C);
463
79.5k
  }
464
56.6k
}
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
41.3k
        : Checkers(checkers), Condition(Cond), Eng(eng) {}
478
479
41.3k
    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
480
41.3k
    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
481
482
    void runChecker(CheckerManager::CheckBranchConditionFunc checkFn,
483
41.7k
                    NodeBuilder &Bldr, ExplodedNode *Pred) {
484
41.7k
      ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(),
485
41.7k
                                     checkFn.Checker);
486
41.7k
      CheckerContext C(Bldr, Eng, Pred, L);
487
41.7k
      checkFn(Condition, C);
488
41.7k
    }
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
41.3k
                                                   ExprEngine &Eng) {
498
41.3k
  ExplodedNodeSet Src;
499
41.3k
  Src.insert(Pred);
500
41.3k
  CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng);
501
41.3k
  expandGraphWithCheckers(C, Dst, Src);
502
41.3k
}
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
1.03k
          Eng(Eng) {}
519
520
1.03k
    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
521
1.03k
    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
522
523
    void runChecker(CheckerManager::CheckNewAllocatorFunc checkFn,
524
624
                    NodeBuilder &Bldr, ExplodedNode *Pred) {
525
624
      ProgramPoint L = PostAllocatorCall(NE, Pred->getLocationContext());
526
624
      CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
527
624
      checkFn(NE, Target, C);
528
624
    }
529
  };
530
531
} // namespace
532
533
void CheckerManager::runCheckersForNewAllocator(
534
    const CXXNewExpr *NE, SVal Target, ExplodedNodeSet &Dst, ExplodedNode *Pred,
535
1.03k
    ExprEngine &Eng, bool WasInlined) {
536
1.03k
  ExplodedNodeSet Src;
537
1.03k
  Src.insert(Pred);
538
1.03k
  CheckNewAllocatorContext C(NewAllocatorCheckers, NE, Target, WasInlined, Eng);
539
1.03k
  expandGraphWithCheckers(C, Dst, Src);
540
1.03k
}
541
542
/// Run checkers for live symbols.
543
void CheckerManager::runCheckersForLiveSymbols(ProgramStateRef state,
544
320k
                                               SymbolReaper &SymReaper) {
545
320k
  for (const auto LiveSymbolsChecker : LiveSymbolsCheckers)
546
114k
    LiveSymbolsChecker(state, SymReaper);
547
320k
}
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
320k
        : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgarmPointKind(K) {}
564
565
320k
    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
566
320k
    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
567
568
    void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
569
991k
                    NodeBuilder &Bldr, ExplodedNode *Pred) {
570
991k
      const ProgramPoint &L = ProgramPoint::getProgramPoint(S, ProgarmPointKind,
571
991k
                                Pred->getLocationContext(), checkFn.Checker);
572
991k
      CheckerContext C(Bldr, Eng, Pred, L);
573
991k
574
991k
      // Note, do not pass the statement to the checkers without letting them
575
991k
      // differentiate if we ran remove dead bindings before or after the
576
991k
      // statement.
577
991k
      checkFn(SR, C);
578
991k
    }
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
320k
                                               ProgramPoint::Kind K) {
590
320k
  CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng, K);
591
320k
  expandGraphWithCheckers(C, Dst, Src);
592
320k
}
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
124k
                                            const CallEvent *Call) {
602
124k
  for (const auto RegionChangesChecker : RegionChangesCheckers) {
603
95.9k
    // If any checker declares the state infeasible (or if it starts that way),
604
95.9k
    // bail out.
605
95.9k
    if (!state)
606
0
      return nullptr;
607
95.9k
    state = RegionChangesChecker(state, invalidated, ExplicitRegions, Regions,
608
95.9k
                                 LCtx, Call);
609
95.9k
  }
610
124k
  return state;
611
124k
}
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
32.3k
                                   RegionAndSymbolInvalidationTraits *ETraits) {
620
32.3k
  assert((Call != nullptr ||
621
32.3k
          (Kind != PSK_DirectEscapeOnCall &&
622
32.3k
           Kind != PSK_IndirectEscapeOnCall)) &&
623
32.3k
         "Call must not be NULL when escaping on call");
624
32.3k
  for (const auto PointerEscapeChecker : PointerEscapeCheckers) {
625
24.5k
    // If any checker declares the state infeasible (or if it starts that
626
24.5k
    //  way), bail out.
627
24.5k
    if (!State)
628
0
      return nullptr;
629
24.5k
    State = PointerEscapeChecker(State, Escaped, Call, Kind, ETraits);
630
24.5k
  }
631
32.3k
  return State;
632
32.3k
}
633
634
/// Run checkers for handling assumptions on symbolic values.
635
ProgramStateRef
636
CheckerManager::runCheckersForEvalAssume(ProgramStateRef state,
637
665k
                                         SVal Cond, bool Assumption) {
638
665k
  for (const auto EvalAssumeChecker : EvalAssumeCheckers) {
639
316k
    // If any checker declares the state infeasible (or if it starts that way),
640
316k
    // bail out.
641
316k
    if (!state)
642
137k
      return nullptr;
643
179k
    state = EvalAssumeChecker(state, Cond, Assumption);
644
179k
  }
645
665k
  
return state527k
;
646
665k
}
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
53.9k
                                            ExprEngine &Eng) {
654
53.9k
  for (const auto Pred : Src) {
655
53.5k
    bool anyEvaluated = false;
656
53.5k
657
53.5k
    ExplodedNodeSet checkDst;
658
53.5k
    NodeBuilder B(Pred, checkDst, Eng.getBuilderContext());
659
53.5k
660
53.5k
    // Check if any of the EvalCall callbacks can evaluate the call.
661
116k
    for (const auto EvalCallChecker : EvalCallCheckers) {
662
116k
      // TODO: Support the situation when the call doesn't correspond
663
116k
      // to any Expr.
664
116k
      ProgramPoint L = ProgramPoint::getProgramPoint(
665
116k
          cast<CallExpr>(Call.getOriginExpr()),
666
116k
          ProgramPoint::PostStmtKind,
667
116k
          Pred->getLocationContext(),
668
116k
          EvalCallChecker.Checker);
669
116k
      bool evaluated = false;
670
116k
      { // CheckerContext generates transitions(populates checkDest) on
671
116k
        // destruction, so introduce the scope to make sure it gets properly
672
116k
        // populated.
673
116k
        CheckerContext C(B, Eng, Pred, L);
674
116k
        evaluated = EvalCallChecker(Call, C);
675
116k
      }
676
116k
      assert(!(evaluated && anyEvaluated)
677
116k
             && "There are more than one checkers evaluating the call");
678
116k
      if (evaluated) {
679
10.3k
        anyEvaluated = true;
680
10.3k
        Dst.insert(checkDst);
681
10.3k
#ifdef NDEBUG
682
10.3k
        break; // on release don't check that no other checker also evals.
683
10.3k
#endif
684
10.3k
      }
685
116k
    }
686
53.5k
687
53.5k
    // If none of the checkers evaluated the call, ask ExprEngine to handle it.
688
53.5k
    if (!anyEvaluated) {
689
43.2k
      NodeBuilder B(Pred, Dst, Eng.getBuilderContext());
690
43.2k
      Eng.defaultEvalCall(B, Pred, Call);
691
43.2k
    }
692
53.5k
  }
693
53.9k
}
694
695
/// Run checkers for the entire Translation Unit.
696
void CheckerManager::runCheckersOnEndOfTranslationUnit(
697
                                                  const TranslationUnitDecl *TU,
698
                                                  AnalysisManager &mgr,
699
886
                                                  BugReporter &BR) {
700
886
  for (const auto EndOfTranslationUnitChecker : EndOfTranslationUnitCheckers)
701
34
    EndOfTranslationUnitChecker(TU, mgr, BR);
702
886
}
703
704
void CheckerManager::runCheckersForPrintStateJson(raw_ostream &Out,
705
                                                  ProgramStateRef State,
706
                                                  const char *NL,
707
                                                  unsigned int Space,
708
4
                                                  bool IsDot) const {
709
4
  Indent(Out, Space, IsDot) << "\"checker_messages\": ";
710
4
711
4
  // Create a temporary stream to see whether we have any message.
712
4
  SmallString<1024> TempBuf;
713
4
  llvm::raw_svector_ostream TempOut(TempBuf);
714
4
  unsigned int InnerSpace = Space + 2;
715
4
716
4
  // Create the new-line in JSON with enough space.
717
4
  SmallString<128> NewLine;
718
4
  llvm::raw_svector_ostream NLOut(NewLine);
719
4
  NLOut << "\", " << NL;                     // Inject the ending and a new line
720
4
  Indent(NLOut, InnerSpace, IsDot) << "\"";  // then begin the next message.
721
4
722
4
  ++Space;
723
4
  bool HasMessage = false;
724
4
725
4
  // Store the last CheckerTag.
726
4
  const void *LastCT = nullptr;
727
41
  for (const auto &CT : CheckerTags) {
728
41
    // See whether the current checker has a message.
729
41
    CT.second->printState(TempOut, State, /*NL=*/NewLine.c_str(), /*Sep=*/"");
730
41
731
41
    if (TempBuf.empty())
732
38
      continue;
733
3
734
3
    if (!HasMessage) {
735
3
      Out << '[' << NL;
736
3
      HasMessage = true;
737
3
    }
738
3
739
3
    LastCT = &CT;
740
3
    TempBuf.clear();
741
3
  }
742
4
743
41
  for (const auto &CT : CheckerTags) {
744
41
    // See whether the current checker has a message.
745
41
    CT.second->printState(TempOut, State, /*NL=*/NewLine.c_str(), /*Sep=*/"");
746
41
747
41
    if (TempBuf.empty())
748
38
      continue;
749
3
750
3
    Indent(Out, Space, IsDot)
751
3
        << "{ \"checker\": \"" << CT.second->getCheckName().getName()
752
3
        << "\", \"messages\": [" << NL;
753
3
    Indent(Out, InnerSpace, IsDot)
754
3
        << '\"' << TempBuf.str().trim() << '\"' << NL;
755
3
    Indent(Out, Space, IsDot) << "]}";
756
3
757
3
    if (&CT != LastCT)
758
0
      Out << ',';
759
3
    Out << NL;
760
3
761
3
    TempBuf.clear();
762
3
  }
763
4
764
4
  // It is the last element of the 'program_state' so do not add a comma.
765
4
  if (HasMessage)
766
3
    Indent(Out, --Space, IsDot) << "]";
767
1
  else
768
1
    Out << "null";
769
4
770
4
  Out << NL;
771
4
}
772
773
//===----------------------------------------------------------------------===//
774
// Internal registration functions for AST traversing.
775
//===----------------------------------------------------------------------===//
776
777
void CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
778
189
                                      HandlesDeclFunc isForDeclFn) {
779
189
  DeclCheckerInfo info = { checkfn, isForDeclFn };
780
189
  DeclCheckers.push_back(info);
781
189
}
782
783
546
void CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
784
546
  BodyCheckers.push_back(checkfn);
785
546
}
786
787
//===----------------------------------------------------------------------===//
788
// Internal registration functions for path-sensitive checking.
789
//===----------------------------------------------------------------------===//
790
791
void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
792
6.25k
                                         HandlesStmtFunc isForStmtFn) {
793
6.25k
  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
794
6.25k
  StmtCheckers.push_back(info);
795
6.25k
}
796
797
void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
798
4.28k
                                          HandlesStmtFunc isForStmtFn) {
799
4.28k
  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
800
4.28k
  StmtCheckers.push_back(info);
801
4.28k
}
802
803
1.49k
void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
804
1.49k
  PreObjCMessageCheckers.push_back(checkfn);
805
1.49k
}
806
807
675
void CheckerManager::_registerForObjCMessageNil(CheckObjCMessageFunc checkfn) {
808
675
  ObjCMessageNilCheckers.push_back(checkfn);
809
675
}
810
811
1.70k
void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
812
1.70k
  PostObjCMessageCheckers.push_back(checkfn);
813
1.70k
}
814
815
3.13k
void CheckerManager::_registerForPreCall(CheckCallFunc checkfn) {
816
3.13k
  PreCallCheckers.push_back(checkfn);
817
3.13k
}
818
1.70k
void CheckerManager::_registerForPostCall(CheckCallFunc checkfn) {
819
1.70k
  PostCallCheckers.push_back(checkfn);
820
1.70k
}
821
822
1.62k
void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
823
1.62k
  LocationCheckers.push_back(checkfn);
824
1.62k
}
825
826
1.59k
void CheckerManager::_registerForBind(CheckBindFunc checkfn) {
827
1.59k
  BindCheckers.push_back(checkfn);
828
1.59k
}
829
830
252
void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
831
252
  EndAnalysisCheckers.push_back(checkfn);
832
252
}
833
834
155
void CheckerManager::_registerForBeginFunction(CheckBeginFunctionFunc checkfn) {
835
155
  BeginFunctionCheckers.push_back(checkfn);
836
155
}
837
838
1.08k
void CheckerManager::_registerForEndFunction(CheckEndFunctionFunc checkfn) {
839
1.08k
  EndFunctionCheckers.push_back(checkfn);
840
1.08k
}
841
842
void CheckerManager::_registerForBranchCondition(
843
750
                                             CheckBranchConditionFunc checkfn) {
844
750
  BranchConditionCheckers.push_back(checkfn);
845
750
}
846
847
187
void CheckerManager::_registerForNewAllocator(CheckNewAllocatorFunc checkfn) {
848
187
  NewAllocatorCheckers.push_back(checkfn);
849
187
}
850
851
214
void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) {
852
214
  LiveSymbolsCheckers.push_back(checkfn);
853
214
}
854
855
1.65k
void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) {
856
1.65k
  DeadSymbolsCheckers.push_back(checkfn);
857
1.65k
}
858
859
326
void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn) {
860
326
  RegionChangesCheckers.push_back(checkfn);
861
326
}
862
863
465
void CheckerManager::_registerForPointerEscape(CheckPointerEscapeFunc checkfn){
864
465
  PointerEscapeCheckers.push_back(checkfn);
865
465
}
866
867
void CheckerManager::_registerForConstPointerEscape(
868
0
                                          CheckPointerEscapeFunc checkfn) {
869
0
  PointerEscapeCheckers.push_back(checkfn);
870
0
}
871
872
313
void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) {
873
313
  EvalAssumeCheckers.push_back(checkfn);
874
313
}
875
876
1.28k
void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
877
1.28k
  EvalCallCheckers.push_back(checkfn);
878
1.28k
}
879
880
void CheckerManager::_registerForEndOfTranslationUnit(
881
34
                                            CheckEndOfTranslationUnit checkfn) {
882
34
  EndOfTranslationUnitCheckers.push_back(checkfn);
883
34
}
884
885
//===----------------------------------------------------------------------===//
886
// Implementation details.
887
//===----------------------------------------------------------------------===//
888
889
const CheckerManager::CachedStmtCheckers &
890
1.31M
CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
891
1.31M
  assert(S);
892
1.31M
893
1.31M
  unsigned Key = (S->getStmtClass() << 1) | unsigned(isPreVisit);
894
1.31M
  CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(Key);
895
1.31M
  if (CCI != CachedStmtCheckersMap.end())
896
1.30M
    return CCI->second;
897
13.2k
898
13.2k
  // Find the checkers that should run for this Stmt and cache them.
899
13.2k
  CachedStmtCheckers &Checkers = CachedStmtCheckersMap[Key];
900
13.2k
  for (const auto &Info : StmtCheckers)
901
181k
    if (Info.IsPreVisit == isPreVisit && 
Info.IsForStmtFn(S)91.6k
)
902
6.85k
      Checkers.push_back(Info.CheckFn);
903
13.2k
  return Checkers;
904
13.2k
}
905
906
918
CheckerManager::~CheckerManager() {
907
918
  for (const auto CheckerDtor : CheckerDtors)
908
13.6k
    CheckerDtor();
909
918
}