/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 | } |