1 //===- AnalyzerOptions.cpp - Analysis Engine Options ----------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains special accessors for analyzer configuration options
10 // with string representations.
12 //===----------------------------------------------------------------------===//
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"
30 using namespace clang
;
34 void AnalyzerOptions::printFormattedEntry(
35 llvm::raw_ostream
&Out
,
36 std::pair
<StringRef
, StringRef
> EntryDescPair
,
37 size_t InitialPad
, size_t EntryWidth
, size_t MinLineWidth
) {
39 llvm::formatted_raw_ostream
FOut(Out
);
41 const size_t PadForDesc
= InitialPad
+ EntryWidth
;
43 FOut
.PadToColumn(InitialPad
) << EntryDescPair
.first
;
44 // If the buffer's length is greater than PadForDesc, print a newline.
45 if (FOut
.getColumn() > PadForDesc
)
48 FOut
.PadToColumn(PadForDesc
);
50 if (MinLineWidth
== 0) {
51 FOut
<< EntryDescPair
.second
;
55 for (char C
: EntryDescPair
.second
) {
56 if (FOut
.getColumn() > MinLineWidth
&& C
== ' ') {
58 FOut
.PadToColumn(PadForDesc
);
65 ExplorationStrategyKind
66 AnalyzerOptions::getExplorationStrategy() const {
68 llvm::StringSwitch
<std::optional
<ExplorationStrategyKind
>>(
70 .Case("dfs", ExplorationStrategyKind::DFS
)
71 .Case("bfs", ExplorationStrategyKind::BFS
)
72 .Case("unexplored_first", ExplorationStrategyKind::UnexploredFirst
)
73 .Case("unexplored_first_queue",
74 ExplorationStrategyKind::UnexploredFirstQueue
)
75 .Case("unexplored_first_location_queue",
76 ExplorationStrategyKind::UnexploredFirstLocationQueue
)
77 .Case("bfs_block_dfs_contents",
78 ExplorationStrategyKind::BFSBlockDFSContents
)
79 .Default(std::nullopt
);
80 assert(K
&& "User mode is invalid.");
84 CTUPhase1InliningKind
AnalyzerOptions::getCTUPhase1Inlining() const {
85 auto K
= llvm::StringSwitch
<std::optional
<CTUPhase1InliningKind
>>(
86 CTUPhase1InliningMode
)
87 .Case("none", CTUPhase1InliningKind::None
)
88 .Case("small", CTUPhase1InliningKind::Small
)
89 .Case("all", CTUPhase1InliningKind::All
)
90 .Default(std::nullopt
);
91 assert(K
&& "CTU inlining mode is invalid.");
95 IPAKind
AnalyzerOptions::getIPAMode() const {
96 auto K
= llvm::StringSwitch
<std::optional
<IPAKind
>>(IPAMode
)
97 .Case("none", IPAK_None
)
98 .Case("basic-inlining", IPAK_BasicInlining
)
99 .Case("inlining", IPAK_Inlining
)
100 .Case("dynamic", IPAK_DynamicDispatch
)
101 .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate
)
102 .Default(std::nullopt
);
103 assert(K
&& "IPA Mode is invalid.");
109 AnalyzerOptions::mayInlineCXXMemberFunction(
110 CXXInlineableMemberKind Param
) const {
111 if (getIPAMode() < IPAK_Inlining
)
114 auto K
= llvm::StringSwitch
<std::optional
<CXXInlineableMemberKind
>>(
115 CXXMemberInliningMode
)
116 .Case("constructors", CIMK_Constructors
)
117 .Case("destructors", CIMK_Destructors
)
118 .Case("methods", CIMK_MemberFunctions
)
119 .Case("none", CIMK_None
)
120 .Default(std::nullopt
);
122 assert(K
&& "Invalid c++ member function inlining mode.");
127 StringRef
AnalyzerOptions::getCheckerStringOption(StringRef CheckerName
,
128 StringRef OptionName
,
129 bool SearchInParents
) const {
130 assert(!CheckerName
.empty() &&
131 "Empty checker name! Make sure the checker object (including it's "
132 "bases!) if fully initialized before calling this function!");
134 ConfigTable::const_iterator E
= Config
.end();
136 ConfigTable::const_iterator I
=
137 Config
.find((Twine(CheckerName
) + ":" + OptionName
).str());
139 return StringRef(I
->getValue());
140 size_t Pos
= CheckerName
.rfind('.');
141 if (Pos
== StringRef::npos
)
144 CheckerName
= CheckerName
.substr(0, Pos
);
145 } while (!CheckerName
.empty() && SearchInParents
);
147 llvm_unreachable("Unknown checker option! Did you call getChecker*Option "
148 "with incorrect parameters? User input must've been "
149 "verified by CheckerRegistry.");
154 StringRef
AnalyzerOptions::getCheckerStringOption(const ento::CheckerBase
*C
,
155 StringRef OptionName
,
156 bool SearchInParents
) const {
157 return getCheckerStringOption(
158 C
->getTagDescription(), OptionName
, SearchInParents
);
161 bool AnalyzerOptions::getCheckerBooleanOption(StringRef CheckerName
,
162 StringRef OptionName
,
163 bool SearchInParents
) const {
165 llvm::StringSwitch
<std::optional
<bool>>(
166 getCheckerStringOption(CheckerName
, OptionName
, SearchInParents
))
168 .Case("false", false)
169 .Default(std::nullopt
);
172 "This option should be either 'true' or 'false', and should've been "
173 "validated by CheckerRegistry!");
178 bool AnalyzerOptions::getCheckerBooleanOption(const ento::CheckerBase
*C
,
179 StringRef OptionName
,
180 bool SearchInParents
) const {
181 return getCheckerBooleanOption(
182 C
->getTagDescription(), OptionName
, SearchInParents
);
185 int AnalyzerOptions::getCheckerIntegerOption(StringRef CheckerName
,
186 StringRef OptionName
,
187 bool SearchInParents
) const {
189 bool HasFailed
= getCheckerStringOption(CheckerName
, OptionName
,
191 .getAsInteger(0, Ret
);
193 "This option should be numeric, and should've been validated by "
199 int AnalyzerOptions::getCheckerIntegerOption(const ento::CheckerBase
*C
,
200 StringRef OptionName
,
201 bool SearchInParents
) const {
202 return getCheckerIntegerOption(
203 C
->getTagDescription(), OptionName
, SearchInParents
);