/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 <utility> |
27 | | #include <vector> |
28 | | |
29 | | using namespace clang; |
30 | | using namespace ento; |
31 | | using namespace llvm; |
32 | | |
33 | | void AnalyzerOptions::printFormattedEntry( |
34 | | llvm::raw_ostream &Out, |
35 | | std::pair<StringRef, StringRef> EntryDescPair, |
36 | 1.21k | size_t InitialPad, size_t EntryWidth, size_t MinLineWidth) { |
37 | | |
38 | 1.21k | llvm::formatted_raw_ostream FOut(Out); |
39 | | |
40 | 1.21k | const size_t PadForDesc = InitialPad + EntryWidth; |
41 | | |
42 | 1.21k | FOut.PadToColumn(InitialPad) << EntryDescPair.first; |
43 | | // If the buffer's length is greater than PadForDesc, print a newline. |
44 | 1.21k | if (FOut.getColumn() > PadForDesc) |
45 | 275 | FOut << '\n'; |
46 | | |
47 | 1.21k | FOut.PadToColumn(PadForDesc); |
48 | | |
49 | 1.21k | if (MinLineWidth == 0) { |
50 | 920 | FOut << EntryDescPair.second; |
51 | 920 | return; |
52 | 920 | } |
53 | | |
54 | 35.3k | for (char C : EntryDescPair.second)291 { |
55 | 35.3k | if (FOut.getColumn() > MinLineWidth && C == ' '3.32k ) { |
56 | 649 | FOut << '\n'; |
57 | 649 | FOut.PadToColumn(PadForDesc); |
58 | 649 | continue; |
59 | 649 | } |
60 | 34.6k | FOut << C; |
61 | 34.6k | } |
62 | 291 | } |
63 | | |
64 | | ExplorationStrategyKind |
65 | 13.8k | AnalyzerOptions::getExplorationStrategy() const { |
66 | 13.8k | auto K = |
67 | 13.8k | llvm::StringSwitch<llvm::Optional<ExplorationStrategyKind>>( |
68 | 13.8k | ExplorationStrategy) |
69 | 13.8k | .Case("dfs", ExplorationStrategyKind::DFS) |
70 | 13.8k | .Case("bfs", ExplorationStrategyKind::BFS) |
71 | 13.8k | .Case("unexplored_first", |
72 | 13.8k | ExplorationStrategyKind::UnexploredFirst) |
73 | 13.8k | .Case("unexplored_first_queue", |
74 | 13.8k | ExplorationStrategyKind::UnexploredFirstQueue) |
75 | 13.8k | .Case("unexplored_first_location_queue", |
76 | 13.8k | ExplorationStrategyKind::UnexploredFirstLocationQueue) |
77 | 13.8k | .Case("bfs_block_dfs_contents", |
78 | 13.8k | ExplorationStrategyKind::BFSBlockDFSContents) |
79 | 13.8k | .Default(None); |
80 | 13.8k | assert(K.hasValue() && "User mode is invalid."); |
81 | 0 | return K.getValue(); |
82 | 13.8k | } |
83 | | |
84 | 154k | IPAKind AnalyzerOptions::getIPAMode() const { |
85 | 154k | auto K = llvm::StringSwitch<llvm::Optional<IPAKind>>(IPAMode) |
86 | 154k | .Case("none", IPAK_None) |
87 | 154k | .Case("basic-inlining", IPAK_BasicInlining) |
88 | 154k | .Case("inlining", IPAK_Inlining) |
89 | 154k | .Case("dynamic", IPAK_DynamicDispatch) |
90 | 154k | .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate) |
91 | 154k | .Default(None); |
92 | 154k | assert(K.hasValue() && "IPA Mode is invalid."); |
93 | | |
94 | 0 | return K.getValue(); |
95 | 154k | } |
96 | | |
97 | | bool |
98 | | AnalyzerOptions::mayInlineCXXMemberFunction( |
99 | 17.3k | CXXInlineableMemberKind Param) const { |
100 | 17.3k | if (getIPAMode() < IPAK_Inlining) |
101 | 0 | return false; |
102 | | |
103 | 17.3k | auto K = |
104 | 17.3k | llvm::StringSwitch<llvm::Optional<CXXInlineableMemberKind>>( |
105 | 17.3k | CXXMemberInliningMode) |
106 | 17.3k | .Case("constructors", CIMK_Constructors) |
107 | 17.3k | .Case("destructors", CIMK_Destructors) |
108 | 17.3k | .Case("methods", CIMK_MemberFunctions) |
109 | 17.3k | .Case("none", CIMK_None) |
110 | 17.3k | .Default(None); |
111 | | |
112 | 17.3k | assert(K.hasValue() && "Invalid c++ member function inlining mode."); |
113 | | |
114 | 0 | return *K >= Param; |
115 | 17.3k | } |
116 | | |
117 | | StringRef AnalyzerOptions::getCheckerStringOption(StringRef CheckerName, |
118 | | StringRef OptionName, |
119 | 10.7k | bool SearchInParents) const { |
120 | 10.7k | assert(!CheckerName.empty() && |
121 | 10.7k | "Empty checker name! Make sure the checker object (including it's " |
122 | 10.7k | "bases!) if fully initialized before calling this function!"); |
123 | | |
124 | 0 | ConfigTable::const_iterator E = Config.end(); |
125 | 10.9k | do { |
126 | 10.9k | ConfigTable::const_iterator I = |
127 | 10.9k | Config.find((Twine(CheckerName) + ":" + OptionName).str()); |
128 | 10.9k | if (I != E) |
129 | 10.7k | return StringRef(I->getValue()); |
130 | 127 | size_t Pos = CheckerName.rfind('.'); |
131 | 127 | if (Pos == StringRef::npos) |
132 | 0 | break; |
133 | | |
134 | 127 | CheckerName = CheckerName.substr(0, Pos); |
135 | 127 | } while (!CheckerName.empty() && SearchInParents); |
136 | | |
137 | 10.7k | llvm_unreachable0 ("Unknown checker option! Did you call getChecker*Option " |
138 | 10.7k | "with incorrect parameters? User input must've been " |
139 | 10.7k | "verified by CheckerRegistry."); |
140 | | |
141 | 0 | return ""; |
142 | 10.7k | } |
143 | | |
144 | | StringRef AnalyzerOptions::getCheckerStringOption(const ento::CheckerBase *C, |
145 | | StringRef OptionName, |
146 | 130 | bool SearchInParents) const { |
147 | 130 | return getCheckerStringOption( |
148 | 130 | C->getTagDescription(), OptionName, SearchInParents); |
149 | 130 | } |
150 | | |
151 | | bool AnalyzerOptions::getCheckerBooleanOption(StringRef CheckerName, |
152 | | StringRef OptionName, |
153 | 10.6k | bool SearchInParents) const { |
154 | 10.6k | auto Ret = llvm::StringSwitch<llvm::Optional<bool>>( |
155 | 10.6k | getCheckerStringOption(CheckerName, OptionName, |
156 | 10.6k | SearchInParents)) |
157 | 10.6k | .Case("true", true) |
158 | 10.6k | .Case("false", false) |
159 | 10.6k | .Default(None); |
160 | | |
161 | 10.6k | assert(Ret && |
162 | 10.6k | "This option should be either 'true' or 'false', and should've been " |
163 | 10.6k | "validated by CheckerRegistry!"); |
164 | | |
165 | 0 | return *Ret; |
166 | 10.6k | } |
167 | | |
168 | | bool AnalyzerOptions::getCheckerBooleanOption(const ento::CheckerBase *C, |
169 | | StringRef OptionName, |
170 | 1.89k | bool SearchInParents) const { |
171 | 1.89k | return getCheckerBooleanOption( |
172 | 1.89k | C->getTagDescription(), OptionName, SearchInParents); |
173 | 1.89k | } |
174 | | |
175 | | int AnalyzerOptions::getCheckerIntegerOption(StringRef CheckerName, |
176 | | StringRef OptionName, |
177 | 38 | bool SearchInParents) const { |
178 | 38 | int Ret = 0; |
179 | 38 | bool HasFailed = getCheckerStringOption(CheckerName, OptionName, |
180 | 38 | SearchInParents) |
181 | 38 | .getAsInteger(0, Ret); |
182 | 38 | assert(!HasFailed && |
183 | 38 | "This option should be numeric, and should've been validated by " |
184 | 38 | "CheckerRegistry!"); |
185 | 0 | (void)HasFailed; |
186 | 38 | return Ret; |
187 | 38 | } |
188 | | |
189 | | int AnalyzerOptions::getCheckerIntegerOption(const ento::CheckerBase *C, |
190 | | StringRef OptionName, |
191 | 38 | bool SearchInParents) const { |
192 | 38 | return getCheckerIntegerOption( |
193 | 38 | C->getTagDescription(), OptionName, SearchInParents); |
194 | 38 | } |