clang  3.9.0
AnalyzerOptions.cpp
Go to the documentation of this file.
1 //===-- AnalyzerOptions.cpp - Analysis Engine Options -----------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains special accessors for analyzer configuration options
11 // with string representations.
12 //
13 //===----------------------------------------------------------------------===//
14 
17 #include "llvm/ADT/SmallString.h"
18 #include "llvm/ADT/StringSwitch.h"
19 #include "llvm/Support/ErrorHandling.h"
20 #include "llvm/Support/raw_ostream.h"
21 
22 using namespace clang;
23 using namespace ento;
24 using namespace llvm;
25 
26 AnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() {
27  if (UserMode == UMK_NotSet) {
28  StringRef ModeStr =
29  Config.insert(std::make_pair("mode", "deep")).first->second;
30  UserMode = llvm::StringSwitch<UserModeKind>(ModeStr)
31  .Case("shallow", UMK_Shallow)
32  .Case("deep", UMK_Deep)
33  .Default(UMK_NotSet);
34  assert(UserMode != UMK_NotSet && "User mode is invalid.");
35  }
36  return UserMode;
37 }
38 
40  if (IPAMode == IPAK_NotSet) {
41 
42  // Use the User Mode to set the default IPA value.
43  // Note, we have to add the string to the Config map for the ConfigDumper
44  // checker to function properly.
45  const char *DefaultIPA = nullptr;
46  UserModeKind HighLevelMode = getUserMode();
47  if (HighLevelMode == UMK_Shallow)
48  DefaultIPA = "inlining";
49  else if (HighLevelMode == UMK_Deep)
50  DefaultIPA = "dynamic-bifurcate";
51  assert(DefaultIPA);
52 
53  // Lookup the ipa configuration option, use the default from User Mode.
54  StringRef ModeStr =
55  Config.insert(std::make_pair("ipa", DefaultIPA)).first->second;
56  IPAKind IPAConfig = llvm::StringSwitch<IPAKind>(ModeStr)
57  .Case("none", IPAK_None)
58  .Case("basic-inlining", IPAK_BasicInlining)
59  .Case("inlining", IPAK_Inlining)
60  .Case("dynamic", IPAK_DynamicDispatch)
61  .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate)
62  .Default(IPAK_NotSet);
63  assert(IPAConfig != IPAK_NotSet && "IPA Mode is invalid.");
64 
65  // Set the member variable.
66  IPAMode = IPAConfig;
67  }
68 
69  return IPAMode;
70 }
71 
72 bool
74  if (getIPAMode() < IPAK_Inlining)
75  return false;
76 
77  if (!CXXMemberInliningMode) {
78  static const char *ModeKey = "c++-inlining";
79 
80  StringRef ModeStr =
81  Config.insert(std::make_pair(ModeKey, "destructors")).first->second;
82 
83  CXXInlineableMemberKind &MutableMode =
84  const_cast<CXXInlineableMemberKind &>(CXXMemberInliningMode);
85 
86  MutableMode = llvm::StringSwitch<CXXInlineableMemberKind>(ModeStr)
87  .Case("constructors", CIMK_Constructors)
88  .Case("destructors", CIMK_Destructors)
89  .Case("none", CIMK_None)
90  .Case("methods", CIMK_MemberFunctions)
91  .Default(CXXInlineableMemberKind());
92 
93  if (!MutableMode) {
94  // FIXME: We should emit a warning here about an unknown inlining kind,
95  // but the AnalyzerOptions doesn't have access to a diagnostic engine.
96  MutableMode = CIMK_None;
97  }
98  }
99 
100  return CXXMemberInliningMode >= K;
101 }
102 
103 static StringRef toString(bool b) { return b ? "true" : "false"; }
104 
105 StringRef AnalyzerOptions::getCheckerOption(StringRef CheckerName,
106  StringRef OptionName,
107  StringRef Default,
108  bool SearchInParents) {
109  // Search for a package option if the option for the checker is not specified
110  // and search in parents is enabled.
111  ConfigTable::const_iterator E = Config.end();
112  do {
113  ConfigTable::const_iterator I =
114  Config.find((Twine(CheckerName) + ":" + OptionName).str());
115  if (I != E)
116  return StringRef(I->getValue());
117  size_t Pos = CheckerName.rfind('.');
118  if (Pos == StringRef::npos)
119  return Default;
120  CheckerName = CheckerName.substr(0, Pos);
121  } while (!CheckerName.empty() && SearchInParents);
122  return Default;
123 }
124 
125 bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal,
126  const CheckerBase *C,
127  bool SearchInParents) {
128  // FIXME: We should emit a warning here if the value is something other than
129  // "true", "false", or the empty string (meaning the default value),
130  // but the AnalyzerOptions doesn't have access to a diagnostic engine.
131  StringRef Default = toString(DefaultVal);
132  StringRef V =
133  C ? getCheckerOption(C->getTagDescription(), Name, Default,
134  SearchInParents)
135  : StringRef(Config.insert(std::make_pair(Name, Default)).first->second);
136  return llvm::StringSwitch<bool>(V)
137  .Case("true", true)
138  .Case("false", false)
139  .Default(DefaultVal);
140 }
141 
143  bool DefaultVal, const CheckerBase *C,
144  bool SearchInParents) {
145  if (!V.hasValue())
146  V = getBooleanOption(Name, DefaultVal, C, SearchInParents);
147  return V.getValue();
148 }
149 
151  return getBooleanOption(IncludeTemporaryDtorsInCFG,
152  "cfg-temporary-dtors",
153  /* Default = */ false);
154 }
155 
157  return getBooleanOption(InlineCXXStandardLibrary,
158  "c++-stdlib-inlining",
159  /*Default=*/true);
160 }
161 
163  return getBooleanOption(InlineTemplateFunctions,
164  "c++-template-inlining",
165  /*Default=*/true);
166 }
167 
169  return getBooleanOption(InlineCXXAllocator,
170  "c++-allocator-inlining",
171  /*Default=*/false);
172 }
173 
175  return getBooleanOption(InlineCXXContainerMethods,
176  "c++-container-inlining",
177  /*Default=*/false);
178 }
179 
181  return getBooleanOption(InlineCXXSharedPtrDtor,
182  "c++-shared_ptr-inlining",
183  /*Default=*/false);
184 }
185 
186 
188  return getBooleanOption(ObjCInliningMode,
189  "objc-inlining",
190  /* Default = */ true);
191 }
192 
194  return getBooleanOption(SuppressNullReturnPaths,
195  "suppress-null-return-paths",
196  /* Default = */ true);
197 }
198 
200  return getBooleanOption(AvoidSuppressingNullArgumentPaths,
201  "avoid-suppressing-null-argument-paths",
202  /* Default = */ false);
203 }
204 
206  return getBooleanOption(SuppressInlinedDefensiveChecks,
207  "suppress-inlined-defensive-checks",
208  /* Default = */ true);
209 }
210 
212  return getBooleanOption(SuppressFromCXXStandardLibrary,
213  "suppress-c++-stdlib",
214  /* Default = */ false);
215 }
216 
218  return getBooleanOption(ReportIssuesInMainSourceFile,
219  "report-in-main-source-file",
220  /* Default = */ false);
221 }
222 
223 
225  return getBooleanOption(StableReportFilename,
226  "stable-report-filename",
227  /* Default = */ false);
228 }
229 
230 int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal,
231  const CheckerBase *C,
232  bool SearchInParents) {
233  SmallString<10> StrBuf;
234  llvm::raw_svector_ostream OS(StrBuf);
235  OS << DefaultVal;
236 
237  StringRef V = C ? getCheckerOption(C->getTagDescription(), Name, OS.str(),
238  SearchInParents)
239  : StringRef(Config.insert(std::make_pair(Name, OS.str()))
240  .first->second);
241 
242  int Res = DefaultVal;
243  bool b = V.getAsInteger(10, Res);
244  assert(!b && "analyzer-config option should be numeric");
245  (void)b;
246  return Res;
247 }
248 
250  StringRef DefaultVal,
251  const CheckerBase *C,
252  bool SearchInParents) {
253  return C ? getCheckerOption(C->getTagDescription(), Name, DefaultVal,
254  SearchInParents)
255  : StringRef(
256  Config.insert(std::make_pair(Name, DefaultVal)).first->second);
257 }
258 
260  if (!AlwaysInlineSize.hasValue())
261  AlwaysInlineSize = getOptionAsInteger("ipa-always-inline-size", 3);
262  return AlwaysInlineSize.getValue();
263 }
264 
266  if (!MaxInlinableSize.hasValue()) {
267 
268  int DefaultValue = 0;
269  UserModeKind HighLevelMode = getUserMode();
270  switch (HighLevelMode) {
271  default:
272  llvm_unreachable("Invalid mode.");
273  case UMK_Shallow:
274  DefaultValue = 4;
275  break;
276  case UMK_Deep:
277  DefaultValue = 50;
278  break;
279  }
280 
281  MaxInlinableSize = getOptionAsInteger("max-inlinable-size", DefaultValue);
282  }
283  return MaxInlinableSize.getValue();
284 }
285 
287  if (!GraphTrimInterval.hasValue())
288  GraphTrimInterval = getOptionAsInteger("graph-trim-interval", 1000);
289  return GraphTrimInterval.getValue();
290 }
291 
293  if (!MaxTimesInlineLarge.hasValue())
294  MaxTimesInlineLarge = getOptionAsInteger("max-times-inline-large", 32);
295  return MaxTimesInlineLarge.getValue();
296 }
297 
299  if (!MinCFGSizeTreatFunctionsAsLarge.hasValue())
300  MinCFGSizeTreatFunctionsAsLarge = getOptionAsInteger(
301  "min-cfg-size-treat-functions-as-large", 14);
302  return MinCFGSizeTreatFunctionsAsLarge.getValue();
303 }
304 
306  if (!MaxNodesPerTopLevelFunction.hasValue()) {
307  int DefaultValue = 0;
308  UserModeKind HighLevelMode = getUserMode();
309  switch (HighLevelMode) {
310  default:
311  llvm_unreachable("Invalid mode.");
312  case UMK_Shallow:
313  DefaultValue = 75000;
314  break;
315  case UMK_Deep:
316  DefaultValue = 150000;
317  break;
318  }
319  MaxNodesPerTopLevelFunction = getOptionAsInteger("max-nodes", DefaultValue);
320  }
321  return MaxNodesPerTopLevelFunction.getValue();
322 }
323 
325  return getBooleanOption("faux-bodies", true);
326 }
327 
329  return getBooleanOption("prune-paths", true);
330 }
331 
333  return getBooleanOption("cfg-conditional-static-initializers", true);
334 }
335 
337  if (!InlineLambdas.hasValue())
338  InlineLambdas = getBooleanOption("inline-lambdas", /*Default=*/true);
339  return InlineLambdas.getValue();
340 }
341 
343  if (!WidenLoops.hasValue())
344  WidenLoops = getBooleanOption("widen-loops", /*Default=*/false);
345  return WidenLoops.getValue();
346 }
Inline C functions and blocks when their definitions are available.
IPAKind
Describes the different modes of inter-procedural analysis.
bool shouldSuppressNullReturnPaths()
Returns whether or not paths that go through null returns should be suppressed.
bool shouldPrunePaths()
Returns whether irrelevant parts of a bug report path should be pruned out of the final output...
bool shouldAvoidSuppressingNullArgumentPaths()
Returns whether a bug report should not be suppressed if its path includes a call with a null argumen...
bool shouldWidenLoops()
Returns true if the analysis should try to widen loops.
Perform only intra-procedural analysis.
A dummy mode in which no C++ inlining is enabled.
bool mayInlineTemplateFunctions()
Returns whether or not templated functions may be considered for inlining.
Inline callees(C, C++, ObjC) when their definitions are available.
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
Definition: Type.h:4549
StringRef getOptionAsString(StringRef Name, StringRef DefaultVal, const ento::CheckerBase *C=nullptr, bool SearchInParents=false)
Query an option's string value.
StringRef getTagDescription() const override
Definition: Checker.cpp:20
bool mayInlineCXXContainerMethods()
Returns whether or not methods of C++ container objects may be considered for inlining.
unsigned getMinCFGSizeTreatFunctionsAsLarge()
Returns the number of basic blocks a function needs to have to be considered large for the 'max-times...
detail::InMemoryDirectory::const_iterator I
UserModeKind getUserMode()
Retrieves and sets the UserMode.
bool shouldSuppressInlinedDefensiveChecks()
Returns whether or not diagnostics containing inlined defensive NULL checks should be suppressed...
bool shouldWriteStableReportFilename()
Returns whether or not the report filename should be random or not.
IPAKind getIPAMode()
Returns the inter-procedural analysis mode.
Refers to regular member function and operator calls.
bool mayInlineObjCMethod()
Returns true if ObjectiveC inlining is enabled, false otherwise.
bool shouldConditionalizeStaticInitializers()
Returns true if 'static' initializers should be in conditional logic in the CFG.
Refers to constructors (implicit or explicit).
Enable inlining of dynamically dispatched methods.
bool getBooleanOption(StringRef Name, bool DefaultVal, const ento::CheckerBase *C=nullptr, bool SearchInParents=false)
Interprets an option's string value as a boolean.
unsigned getMaxNodesPerTopLevelFunction()
Returns the maximum number of nodes the analyzer can generate while exploring a top level function (f...
bool mayInlineCXXStandardLibrary()
Returns whether or not C++ standard library functions may be considered for inlining.
Refers to destructors (implicit or explicit).
unsigned getGraphTrimInterval()
Returns how often nodes in the ExplodedGraph should be recycled to save memory.
detail::InMemoryDirectory::const_iterator E
bool includeTemporaryDtorsInCFG()
Returns whether or not the destructors for C++ temporary objects should be included in the CFG...
bool shouldSuppressFromCXXStandardLibrary()
Returns whether or not diagnostics reported within the C++ standard library should be suppressed...
bool shouldSynthesizeBodies()
Returns true if the analyzer engine should synthesize fake bodies for well-known functions.
bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K)
Returns the option controlling which C++ member functions will be considered for inlining.
unsigned getMaxTimesInlineLarge()
Returns the maximum times a large function could be inlined.
CXXInlineableMemberKind
Describes the different kinds of C++ member functions which can be considered for inlining by the ana...
int getOptionAsInteger(StringRef Name, int DefaultVal, const ento::CheckerBase *C=nullptr, bool SearchInParents=false)
Interprets an option's string value as an integer value.
bool mayInlineCXXAllocator()
Returns whether or not allocator call may be considered for inlining.
Enable inlining of dynamically dispatched methods, bifurcate paths when exact type info is unavailabl...
bool mayInlineCXXSharedPtrDtor()
Returns whether or not the destructor of C++ 'shared_ptr' may be considered for inlining.
bool shouldReportIssuesInMainSourceFile()
Returns whether or not the diagnostic report should be always reported in the main source file and no...
bool shouldInlineLambdas()
Returns true if lambdas should be inlined.
static StringRef toString(bool b)