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"
29 using namespace clang;
33 void AnalyzerOptions::printFormattedEntry(
34 llvm::raw_ostream &Out,
35 std::pair<StringRef, StringRef> EntryDescPair,
36 size_t InitialPad, size_t EntryWidth, size_t MinLineWidth) {
38 llvm::formatted_raw_ostream FOut(Out);
40 const size_t PadForDesc = InitialPad + EntryWidth;
42 FOut.PadToColumn(InitialPad) << EntryDescPair.first;
43 // If the buffer's length is greater than PadForDesc, print a newline.
44 if (FOut.getColumn() > PadForDesc)
47 FOut.PadToColumn(PadForDesc);
49 if (MinLineWidth == 0) {
50 FOut << EntryDescPair.second;
54 for (char C : EntryDescPair.second) {
55 if (FOut.getColumn() > MinLineWidth && C == ' ') {
57 FOut.PadToColumn(PadForDesc);
64 ExplorationStrategyKind
65 AnalyzerOptions::getExplorationStrategy() const {
67 llvm::StringSwitch<llvm::Optional<ExplorationStrategyKind>>(
69 .Case("dfs", ExplorationStrategyKind::DFS)
70 .Case("bfs", ExplorationStrategyKind::BFS)
71 .Case("unexplored_first",
72 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)
80 assert(K.hasValue() && "User mode is invalid.");
84 IPAKind AnalyzerOptions::getIPAMode() const {
85 auto K = llvm::StringSwitch<llvm::Optional<IPAKind>>(IPAMode)
86 .Case("none", IPAK_None)
87 .Case("basic-inlining", IPAK_BasicInlining)
88 .Case("inlining", IPAK_Inlining)
89 .Case("dynamic", IPAK_DynamicDispatch)
90 .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate)
92 assert(K.hasValue() && "IPA Mode is invalid.");
98 AnalyzerOptions::mayInlineCXXMemberFunction(
99 CXXInlineableMemberKind Param) const {
100 if (getIPAMode() < IPAK_Inlining)
104 llvm::StringSwitch<llvm::Optional<CXXInlineableMemberKind>>(
105 CXXMemberInliningMode)
106 .Case("constructors", CIMK_Constructors)
107 .Case("destructors", CIMK_Destructors)
108 .Case("methods", CIMK_MemberFunctions)
109 .Case("none", CIMK_None)
112 assert(K.hasValue() && "Invalid c++ member function inlining mode.");
117 StringRef AnalyzerOptions::getCheckerStringOption(StringRef CheckerName,
118 StringRef OptionName,
119 bool SearchInParents) const {
120 assert(!CheckerName.empty() &&
121 "Empty checker name! Make sure the checker object (including it's "
122 "bases!) if fully initialized before calling this function!");
124 ConfigTable::const_iterator E = Config.end();
126 ConfigTable::const_iterator I =
127 Config.find((Twine(CheckerName) + ":" + OptionName).str());
129 return StringRef(I->getValue());
130 size_t Pos = CheckerName.rfind('.');
131 if (Pos == StringRef::npos)
134 CheckerName = CheckerName.substr(0, Pos);
135 } while (!CheckerName.empty() && SearchInParents);
137 llvm_unreachable("Unknown checker option! Did you call getChecker*Option "
138 "with incorrect parameters? User input must've been "
139 "verified by CheckerRegistry.");
144 StringRef AnalyzerOptions::getCheckerStringOption(const ento::CheckerBase *C,
145 StringRef OptionName,
146 bool SearchInParents) const {
147 return getCheckerStringOption(
148 C->getTagDescription(), OptionName, SearchInParents);
151 bool AnalyzerOptions::getCheckerBooleanOption(StringRef CheckerName,
152 StringRef OptionName,
153 bool SearchInParents) const {
154 auto Ret = llvm::StringSwitch<llvm::Optional<bool>>(
155 getCheckerStringOption(CheckerName, OptionName,
158 .Case("false", false)
162 "This option should be either 'true' or 'false', and should've been "
163 "validated by CheckerRegistry!");
168 bool AnalyzerOptions::getCheckerBooleanOption(const ento::CheckerBase *C,
169 StringRef OptionName,
170 bool SearchInParents) const {
171 return getCheckerBooleanOption(
172 C->getTagDescription(), OptionName, SearchInParents);
175 int AnalyzerOptions::getCheckerIntegerOption(StringRef CheckerName,
176 StringRef OptionName,
177 bool SearchInParents) const {
179 bool HasFailed = getCheckerStringOption(CheckerName, OptionName,
181 .getAsInteger(0, Ret);
183 "This option should be numeric, and should've been validated by "
189 int AnalyzerOptions::getCheckerIntegerOption(const ento::CheckerBase *C,
190 StringRef OptionName,
191 bool SearchInParents) const {
192 return getCheckerIntegerOption(
193 C->getTagDescription(), OptionName, SearchInParents);