Coverage Report

Created: 2023-09-12 09:32

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- AnalyzerOptions.cpp - Analysis Engine Options ----------------------===//
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
// This file contains special accessors for analyzer configuration options
10
// with string representations.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
15
#include "clang/StaticAnalyzer/Core/Checker.h"
16
#include "llvm/ADT/SmallString.h"
17
#include "llvm/ADT/StringSwitch.h"
18
#include "llvm/ADT/StringRef.h"
19
#include "llvm/ADT/Twine.h"
20
#include "llvm/Support/ErrorHandling.h"
21
#include "llvm/Support/FileSystem.h"
22
#include "llvm/Support/FormattedStream.h"
23
#include "llvm/Support/raw_ostream.h"
24
#include <cassert>
25
#include <cstddef>
26
#include <optional>
27
#include <utility>
28
#include <vector>
29
30
using namespace clang;
31
using namespace ento;
32
using namespace llvm;
33
34
void AnalyzerOptions::printFormattedEntry(
35
    llvm::raw_ostream &Out,
36
    std::pair<StringRef, StringRef> EntryDescPair,
37
1.27k
    size_t InitialPad, size_t EntryWidth, size_t MinLineWidth) {
38
39
1.27k
  llvm::formatted_raw_ostream FOut(Out);
40
41
1.27k
  const size_t PadForDesc = InitialPad + EntryWidth;
42
43
1.27k
  FOut.PadToColumn(InitialPad) << EntryDescPair.first;
44
  // If the buffer's length is greater than PadForDesc, print a newline.
45
1.27k
  if (FOut.getColumn() > PadForDesc)
46
297
    FOut << '\n';
47
48
1.27k
  FOut.PadToColumn(PadForDesc);
49
50
1.27k
  if (MinLineWidth == 0) {
51
958
    FOut << EntryDescPair.second;
52
958
    return;
53
958
  }
54
55
40.0k
  
for (char C : EntryDescPair.second)316
{
56
40.0k
    if (FOut.getColumn() > MinLineWidth && 
C == ' '3.78k
) {
57
746
      FOut << '\n';
58
746
      FOut.PadToColumn(PadForDesc);
59
746
      continue;
60
746
    }
61
39.3k
    FOut << C;
62
39.3k
  }
63
316
}
64
65
ExplorationStrategyKind
66
16.2k
AnalyzerOptions::getExplorationStrategy() const {
67
16.2k
  auto K =
68
16.2k
      llvm::StringSwitch<std::optional<ExplorationStrategyKind>>(
69
16.2k
          ExplorationStrategy)
70
16.2k
          .Case("dfs", ExplorationStrategyKind::DFS)
71
16.2k
          .Case("bfs", ExplorationStrategyKind::BFS)
72
16.2k
          .Case("unexplored_first", ExplorationStrategyKind::UnexploredFirst)
73
16.2k
          .Case("unexplored_first_queue",
74
16.2k
                ExplorationStrategyKind::UnexploredFirstQueue)
75
16.2k
          .Case("unexplored_first_location_queue",
76
16.2k
                ExplorationStrategyKind::UnexploredFirstLocationQueue)
77
16.2k
          .Case("bfs_block_dfs_contents",
78
16.2k
                ExplorationStrategyKind::BFSBlockDFSContents)
79
16.2k
          .Default(std::nullopt);
80
16.2k
  assert(K && "User mode is invalid.");
81
16.2k
  return *K;
82
16.2k
}
83
84
124
CTUPhase1InliningKind AnalyzerOptions::getCTUPhase1Inlining() const {
85
124
  auto K = llvm::StringSwitch<std::optional<CTUPhase1InliningKind>>(
86
124
               CTUPhase1InliningMode)
87
124
               .Case("none", CTUPhase1InliningKind::None)
88
124
               .Case("small", CTUPhase1InliningKind::Small)
89
124
               .Case("all", CTUPhase1InliningKind::All)
90
124
               .Default(std::nullopt);
91
124
  assert(K && "CTU inlining mode is invalid.");
92
124
  return *K;
93
124
}
94
95
158k
IPAKind AnalyzerOptions::getIPAMode() const {
96
158k
  auto K = llvm::StringSwitch<std::optional<IPAKind>>(IPAMode)
97
158k
               .Case("none", IPAK_None)
98
158k
               .Case("basic-inlining", IPAK_BasicInlining)
99
158k
               .Case("inlining", IPAK_Inlining)
100
158k
               .Case("dynamic", IPAK_DynamicDispatch)
101
158k
               .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate)
102
158k
               .Default(std::nullopt);
103
158k
  assert(K && "IPA Mode is invalid.");
104
105
158k
  return *K;
106
158k
}
107
108
bool
109
AnalyzerOptions::mayInlineCXXMemberFunction(
110
18.1k
                                          CXXInlineableMemberKind Param) const {
111
18.1k
  if (getIPAMode() < IPAK_Inlining)
112
0
    return false;
113
114
18.1k
  auto K = llvm::StringSwitch<std::optional<CXXInlineableMemberKind>>(
115
18.1k
               CXXMemberInliningMode)
116
18.1k
               .Case("constructors", CIMK_Constructors)
117
18.1k
               .Case("destructors", CIMK_Destructors)
118
18.1k
               .Case("methods", CIMK_MemberFunctions)
119
18.1k
               .Case("none", CIMK_None)
120
18.1k
               .Default(std::nullopt);
121
122
18.1k
  assert(K && "Invalid c++ member function inlining mode.");
123
124
18.1k
  return *K >= Param;
125
18.1k
}
126
127
StringRef AnalyzerOptions::getCheckerStringOption(StringRef CheckerName,
128
                                                  StringRef OptionName,
129
15.6k
                                                  bool SearchInParents) const {
130
15.6k
  assert(!CheckerName.empty() &&
131
15.6k
         "Empty checker name! Make sure the checker object (including it's "
132
15.6k
         "bases!) if fully initialized before calling this function!");
133
134
15.6k
  ConfigTable::const_iterator E = Config.end();
135
15.7k
  do {
136
15.7k
    ConfigTable::const_iterator I =
137
15.7k
        Config.find((Twine(CheckerName) + ":" + OptionName).str());
138
15.7k
    if (I != E)
139
15.6k
      return StringRef(I->getValue());
140
150
    size_t Pos = CheckerName.rfind('.');
141
150
    if (Pos == StringRef::npos)
142
0
      break;
143
144
150
    CheckerName = CheckerName.substr(0, Pos);
145
150
  } while (!CheckerName.empty() && SearchInParents);
146
147
0
  llvm_unreachable("Unknown checker option! Did you call getChecker*Option "
148
0
                   "with incorrect parameters? User input must've been "
149
0
                   "verified by CheckerRegistry.");
150
151
0
  return "";
152
15.6k
}
153
154
StringRef AnalyzerOptions::getCheckerStringOption(const ento::CheckerBase *C,
155
                                                  StringRef OptionName,
156
147
                                                  bool SearchInParents) const {
157
147
  return getCheckerStringOption(
158
147
                           C->getTagDescription(), OptionName, SearchInParents);
159
147
}
160
161
bool AnalyzerOptions::getCheckerBooleanOption(StringRef CheckerName,
162
                                              StringRef OptionName,
163
15.4k
                                              bool SearchInParents) const {
164
15.4k
  auto Ret =
165
15.4k
      llvm::StringSwitch<std::optional<bool>>(
166
15.4k
          getCheckerStringOption(CheckerName, OptionName, SearchInParents))
167
15.4k
          .Case("true", true)
168
15.4k
          .Case("false", false)
169
15.4k
          .Default(std::nullopt);
170
171
15.4k
  assert(Ret &&
172
15.4k
         "This option should be either 'true' or 'false', and should've been "
173
15.4k
         "validated by CheckerRegistry!");
174
175
15.4k
  return *Ret;
176
15.4k
}
177
178
bool AnalyzerOptions::getCheckerBooleanOption(const ento::CheckerBase *C,
179
                                              StringRef OptionName,
180
3.83k
                                              bool SearchInParents) const {
181
3.83k
  return getCheckerBooleanOption(
182
3.83k
             C->getTagDescription(), OptionName, SearchInParents);
183
3.83k
}
184
185
int AnalyzerOptions::getCheckerIntegerOption(StringRef CheckerName,
186
                                             StringRef OptionName,
187
39
                                             bool SearchInParents) const {
188
39
  int Ret = 0;
189
39
  bool HasFailed = getCheckerStringOption(CheckerName, OptionName,
190
39
                                          SearchInParents)
191
39
                     .getAsInteger(0, Ret);
192
39
  assert(!HasFailed &&
193
39
         "This option should be numeric, and should've been validated by "
194
39
         "CheckerRegistry!");
195
39
  (void)HasFailed;
196
39
  return Ret;
197
39
}
198
199
int AnalyzerOptions::getCheckerIntegerOption(const ento::CheckerBase *C,
200
                                             StringRef OptionName,
201
39
                                             bool SearchInParents) const {
202
39
  return getCheckerIntegerOption(
203
39
                           C->getTagDescription(), OptionName, SearchInParents);
204
39
}