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

source code of clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp