clang  7.0.0svn
AnalyzerOptions.cpp
Go to the documentation of this file.
1 //===- AnalyzerOptions.cpp - Analysis Engine Options ----------------------===//
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/ADT/StringRef.h"
20 #include "llvm/ADT/Twine.h"
21 #include "llvm/Support/ErrorHandling.h"
22 #include "llvm/Support/FileSystem.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 std::vector<StringRef>
34 AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental /* = false */) {
35  static const StringRef StaticAnalyzerChecks[] = {
36 #define GET_CHECKERS
37 #define CHECKER(FULLNAME, CLASS, DESCFILE, HELPTEXT, GROUPINDEX, HIDDEN) \
38  FULLNAME,
39 #include "clang/StaticAnalyzer/Checkers/Checkers.inc"
40 #undef CHECKER
41 #undef GET_CHECKERS
42  };
43  std::vector<StringRef> Result;
44  for (StringRef CheckName : StaticAnalyzerChecks) {
45  if (!CheckName.startswith("debug.") &&
46  (IncludeExperimental || !CheckName.startswith("alpha.")))
47  Result.push_back(CheckName);
48  }
49  return Result;
50 }
51 
52 AnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() {
53  if (UserMode == UMK_NotSet) {
54  StringRef ModeStr =
55  Config.insert(std::make_pair("mode", "deep")).first->second;
56  UserMode = llvm::StringSwitch<UserModeKind>(ModeStr)
57  .Case("shallow", UMK_Shallow)
58  .Case("deep", UMK_Deep)
59  .Default(UMK_NotSet);
60  assert(UserMode != UMK_NotSet && "User mode is invalid.");
61  }
62  return UserMode;
63 }
64 
67  if (ExplorationStrategy == ExplorationStrategyKind::NotSet) {
68  StringRef StratStr =
69  Config
70  .insert(std::make_pair("exploration_strategy", "unexplored_first_queue"))
71  .first->second;
72  ExplorationStrategy =
73  llvm::StringSwitch<ExplorationStrategyKind>(StratStr)
74  .Case("dfs", ExplorationStrategyKind::DFS)
75  .Case("bfs", ExplorationStrategyKind::BFS)
76  .Case("unexplored_first",
77  ExplorationStrategyKind::UnexploredFirst)
78  .Case("unexplored_first_queue",
79  ExplorationStrategyKind::UnexploredFirstQueue)
80  .Case("bfs_block_dfs_contents",
81  ExplorationStrategyKind::BFSBlockDFSContents)
82  .Default(ExplorationStrategyKind::NotSet);
83  assert(ExplorationStrategy != ExplorationStrategyKind::NotSet &&
84  "User mode is invalid.");
85  }
86  return ExplorationStrategy;
87 }
88 
90  if (IPAMode == IPAK_NotSet) {
91  // Use the User Mode to set the default IPA value.
92  // Note, we have to add the string to the Config map for the ConfigDumper
93  // checker to function properly.
94  const char *DefaultIPA = nullptr;
95  UserModeKind HighLevelMode = getUserMode();
96  if (HighLevelMode == UMK_Shallow)
97  DefaultIPA = "inlining";
98  else if (HighLevelMode == UMK_Deep)
99  DefaultIPA = "dynamic-bifurcate";
100  assert(DefaultIPA);
101 
102  // Lookup the ipa configuration option, use the default from User Mode.
103  StringRef ModeStr =
104  Config.insert(std::make_pair("ipa", DefaultIPA)).first->second;
105  IPAKind IPAConfig = llvm::StringSwitch<IPAKind>(ModeStr)
106  .Case("none", IPAK_None)
107  .Case("basic-inlining", IPAK_BasicInlining)
108  .Case("inlining", IPAK_Inlining)
109  .Case("dynamic", IPAK_DynamicDispatch)
110  .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate)
111  .Default(IPAK_NotSet);
112  assert(IPAConfig != IPAK_NotSet && "IPA Mode is invalid.");
113 
114  // Set the member variable.
115  IPAMode = IPAConfig;
116  }
117 
118  return IPAMode;
119 }
120 
121 bool
123  if (getIPAMode() < IPAK_Inlining)
124  return false;
125 
126  if (!CXXMemberInliningMode) {
127  static const char *ModeKey = "c++-inlining";
128 
129  StringRef ModeStr =
130  Config.insert(std::make_pair(ModeKey, "destructors")).first->second;
131 
132  CXXInlineableMemberKind &MutableMode =
133  const_cast<CXXInlineableMemberKind &>(CXXMemberInliningMode);
134 
135  MutableMode = llvm::StringSwitch<CXXInlineableMemberKind>(ModeStr)
136  .Case("constructors", CIMK_Constructors)
137  .Case("destructors", CIMK_Destructors)
138  .Case("none", CIMK_None)
139  .Case("methods", CIMK_MemberFunctions)
140  .Default(CXXInlineableMemberKind());
141 
142  if (!MutableMode) {
143  // FIXME: We should emit a warning here about an unknown inlining kind,
144  // but the AnalyzerOptions doesn't have access to a diagnostic engine.
145  MutableMode = CIMK_None;
146  }
147  }
148 
149  return CXXMemberInliningMode >= K;
150 }
151 
152 static StringRef toString(bool b) { return b ? "true" : "false"; }
153 
154 StringRef AnalyzerOptions::getCheckerOption(StringRef CheckerName,
155  StringRef OptionName,
156  StringRef Default,
157  bool SearchInParents) {
158  // Search for a package option if the option for the checker is not specified
159  // and search in parents is enabled.
160  ConfigTable::const_iterator E = Config.end();
161  do {
162  ConfigTable::const_iterator I =
163  Config.find((Twine(CheckerName) + ":" + OptionName).str());
164  if (I != E)
165  return StringRef(I->getValue());
166  size_t Pos = CheckerName.rfind('.');
167  if (Pos == StringRef::npos)
168  return Default;
169  CheckerName = CheckerName.substr(0, Pos);
170  } while (!CheckerName.empty() && SearchInParents);
171  return Default;
172 }
173 
174 bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal,
175  const CheckerBase *C,
176  bool SearchInParents) {
177  // FIXME: We should emit a warning here if the value is something other than
178  // "true", "false", or the empty string (meaning the default value),
179  // but the AnalyzerOptions doesn't have access to a diagnostic engine.
180  StringRef Default = toString(DefaultVal);
181  StringRef V =
182  C ? getCheckerOption(C->getTagDescription(), Name, Default,
183  SearchInParents)
184  : StringRef(Config.insert(std::make_pair(Name, Default)).first->second);
185  return llvm::StringSwitch<bool>(V)
186  .Case("true", true)
187  .Case("false", false)
188  .Default(DefaultVal);
189 }
190 
192  bool DefaultVal, const CheckerBase *C,
193  bool SearchInParents) {
194  if (!V.hasValue())
195  V = getBooleanOption(Name, DefaultVal, C, SearchInParents);
196  return V.getValue();
197 }
198 
200  return getBooleanOption(IncludeTemporaryDtorsInCFG,
201  "cfg-temporary-dtors",
202  /* Default = */ true);
203 }
204 
206  return getBooleanOption(IncludeImplicitDtorsInCFG,
207  "cfg-implicit-dtors",
208  /* Default = */ true);
209 }
210 
212  return getBooleanOption(IncludeLifetimeInCFG, "cfg-lifetime",
213  /* Default = */ false);
214 }
215 
217  return getBooleanOption(IncludeLoopExitInCFG, "cfg-loopexit",
218  /* Default = */ false);
219 }
220 
222  return getBooleanOption(IncludeRichConstructorsInCFG,
223  "cfg-rich-constructors",
224  /* Default = */ true);
225 }
226 
228  return getBooleanOption(IncludeScopesInCFG,
229  "cfg-scopes",
230  /* Default = */ false);
231 }
232 
234  return getBooleanOption(InlineCXXStandardLibrary,
235  "c++-stdlib-inlining",
236  /*Default=*/true);
237 }
238 
240  return getBooleanOption(InlineTemplateFunctions,
241  "c++-template-inlining",
242  /*Default=*/true);
243 }
244 
246  return getBooleanOption(InlineCXXAllocator,
247  "c++-allocator-inlining",
248  /*Default=*/true);
249 }
250 
252  return getBooleanOption(InlineCXXContainerMethods,
253  "c++-container-inlining",
254  /*Default=*/false);
255 }
256 
258  return getBooleanOption(InlineCXXSharedPtrDtor,
259  "c++-shared_ptr-inlining",
260  /*Default=*/false);
261 }
262 
264  return getBooleanOption(InlineCXXTemporaryDtors,
265  "c++-temp-dtor-inlining",
266  /*Default=*/true);
267 }
268 
270  return getBooleanOption(ObjCInliningMode,
271  "objc-inlining",
272  /* Default = */ true);
273 }
274 
276  return getBooleanOption(SuppressNullReturnPaths,
277  "suppress-null-return-paths",
278  /* Default = */ true);
279 }
280 
282  return getBooleanOption(AvoidSuppressingNullArgumentPaths,
283  "avoid-suppressing-null-argument-paths",
284  /* Default = */ false);
285 }
286 
288  return getBooleanOption(SuppressInlinedDefensiveChecks,
289  "suppress-inlined-defensive-checks",
290  /* Default = */ true);
291 }
292 
294  return getBooleanOption(SuppressFromCXXStandardLibrary,
295  "suppress-c++-stdlib",
296  /* Default = */ true);
297 }
298 
300  return getBooleanOption(CrosscheckWithZ3,
301  "crosscheck-with-z3",
302  /* Default = */ false);
303 }
304 
306  return getBooleanOption(ReportIssuesInMainSourceFile,
307  "report-in-main-source-file",
308  /* Default = */ false);
309 }
310 
311 
313  return getBooleanOption(StableReportFilename,
314  "stable-report-filename",
315  /* Default = */ false);
316 }
317 
319  return getBooleanOption(SerializeStats,
320  "serialize-stats",
321  /* Default = */ false);
322 }
323 
324 int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal,
325  const CheckerBase *C,
326  bool SearchInParents) {
327  SmallString<10> StrBuf;
328  llvm::raw_svector_ostream OS(StrBuf);
329  OS << DefaultVal;
330 
331  StringRef V = C ? getCheckerOption(C->getTagDescription(), Name, OS.str(),
332  SearchInParents)
333  : StringRef(Config.insert(std::make_pair(Name, OS.str()))
334  .first->second);
335 
336  int Res = DefaultVal;
337  bool b = V.getAsInteger(10, Res);
338  assert(!b && "analyzer-config option should be numeric");
339  (void)b;
340  return Res;
341 }
342 
343 StringRef AnalyzerOptions::getOptionAsString(StringRef Name,
344  StringRef DefaultVal,
345  const CheckerBase *C,
346  bool SearchInParents) {
347  return C ? getCheckerOption(C->getTagDescription(), Name, DefaultVal,
348  SearchInParents)
349  : StringRef(
350  Config.insert(std::make_pair(Name, DefaultVal)).first->second);
351 }
352 
354  if (!AlwaysInlineSize.hasValue())
355  AlwaysInlineSize = getOptionAsInteger("ipa-always-inline-size", 3);
356  return AlwaysInlineSize.getValue();
357 }
358 
360  if (!MaxInlinableSize.hasValue()) {
361  int DefaultValue = 0;
362  UserModeKind HighLevelMode = getUserMode();
363  switch (HighLevelMode) {
364  default:
365  llvm_unreachable("Invalid mode.");
366  case UMK_Shallow:
367  DefaultValue = 4;
368  break;
369  case UMK_Deep:
370  DefaultValue = 100;
371  break;
372  }
373 
374  MaxInlinableSize = getOptionAsInteger("max-inlinable-size", DefaultValue);
375  }
376  return MaxInlinableSize.getValue();
377 }
378 
380  if (!GraphTrimInterval.hasValue())
381  GraphTrimInterval = getOptionAsInteger("graph-trim-interval", 1000);
382  return GraphTrimInterval.getValue();
383 }
384 
386  if (!MaxTimesInlineLarge.hasValue())
387  MaxTimesInlineLarge = getOptionAsInteger("max-times-inline-large", 32);
388  return MaxTimesInlineLarge.getValue();
389 }
390 
392  if (!MinCFGSizeTreatFunctionsAsLarge.hasValue())
393  MinCFGSizeTreatFunctionsAsLarge = getOptionAsInteger(
394  "min-cfg-size-treat-functions-as-large", 14);
395  return MinCFGSizeTreatFunctionsAsLarge.getValue();
396 }
397 
399  if (!MaxNodesPerTopLevelFunction.hasValue()) {
400  int DefaultValue = 0;
401  UserModeKind HighLevelMode = getUserMode();
402  switch (HighLevelMode) {
403  default:
404  llvm_unreachable("Invalid mode.");
405  case UMK_Shallow:
406  DefaultValue = 75000;
407  break;
408  case UMK_Deep:
409  DefaultValue = 225000;
410  break;
411  }
412  MaxNodesPerTopLevelFunction = getOptionAsInteger("max-nodes", DefaultValue);
413  }
414  return MaxNodesPerTopLevelFunction.getValue();
415 }
416 
418  return getBooleanOption("faux-bodies", true);
419 }
420 
422  return getBooleanOption("prune-paths", true);
423 }
424 
426  return getBooleanOption("cfg-conditional-static-initializers", true);
427 }
428 
430  if (!InlineLambdas.hasValue())
431  InlineLambdas = getBooleanOption("inline-lambdas", /*Default=*/true);
432  return InlineLambdas.getValue();
433 }
434 
436  if (!WidenLoops.hasValue())
437  WidenLoops = getBooleanOption("widen-loops", /*Default=*/false);
438  return WidenLoops.getValue();
439 }
440 
442  if (!UnrollLoops.hasValue())
443  UnrollLoops = getBooleanOption("unroll-loops", /*Default=*/false);
444  return UnrollLoops.getValue();
445 }
446 
448  if (!DisplayNotesAsEvents.hasValue())
449  DisplayNotesAsEvents =
450  getBooleanOption("notes-as-events", /*Default=*/false);
451  return DisplayNotesAsEvents.getValue();
452 }
453 
455  if (!AggressiveRelationalComparisonSimplification.hasValue())
456  AggressiveRelationalComparisonSimplification =
457  getBooleanOption("aggressive-relational-comparison-simplification",
458  /*Default=*/false);
459  return AggressiveRelationalComparisonSimplification.getValue();
460 }
461 
463  if (!CTUDir.hasValue()) {
464  CTUDir = getOptionAsString("ctu-dir", "");
465  if (!llvm::sys::fs::is_directory(*CTUDir))
466  CTUDir = "";
467  }
468  return CTUDir.getValue();
469 }
470 
472  if (!NaiveCTU.hasValue()) {
473  NaiveCTU = getBooleanOption("experimental-enable-naive-ctu-analysis",
474  /*Default=*/false);
475  }
476  return NaiveCTU.getValue();
477 }
478 
480  if (!CTUIndexName.hasValue())
481  CTUIndexName = getOptionAsString("ctu-index-name", "externalFnMap.txt");
482  return CTUIndexName.getValue();
483 }
Inline C functions and blocks when their definitions are available.
bool shouldDisplayNotesAsEvents()
Returns true if the bug reporter should transparently treat extra note diagnostic pieces as event dia...
IPAKind
Describes the different modes of inter-procedural analysis.
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
Definition: Dominators.h:30
bool shouldSuppressNullReturnPaths()
Returns whether or not paths that go through null returns should be suppressed.
bool mayInlineCXXTemporaryDtors()
Returns true if C++ temporary destructors should be inlined during analysis.
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 includeRichConstructorsInCFG()
Returns whether or not construction site information should be included in the CFG C++ constructor el...
bool mayInlineTemplateFunctions()
Returns whether or not templated functions may be considered for inlining.
Inline callees(C, C++, ObjC) when their definitions are available.
StringRef getCTUDir()
Returns the directory containing the CTU related files.
bool includeScopesInCFG()
Returns whether or not scope information should be included in the CFG.
StringRef getOptionAsString(StringRef Name, StringRef DefaultVal, const ento::CheckerBase *C=nullptr, bool SearchInParents=false)
Query an option&#39;s string value.
bool includeLoopExitInCFG()
Returns whether or not the end of the loop information should be included in the CFG.
StringRef getTagDescription() const override
Definition: Checker.cpp:20
bool mayInlineCXXContainerMethods()
Returns whether or not methods of C++ container objects may be considered for inlining.
static std::vector< StringRef > getRegisteredCheckers(bool IncludeExperimental=false)
bool includeLifetimeInCFG()
Returns whether or not end-of-lifetime information should be included in the CFG. ...
unsigned getMinCFGSizeTreatFunctionsAsLarge()
Returns the number of basic blocks a function needs to have to be considered large for the &#39;max-times...
bool shouldUnrollLoops()
Returns true if the analysis should try to unroll loops with known bounds.
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 &#39;static&#39; initializers should be in conditional logic in the CFG.
Refers to constructors (implicit or explicit).
bool shouldAggressivelySimplifyRelationalComparison()
Returns true if SValBuilder should rearrange comparisons of symbolic expressions which consist of a s...
Enable inlining of dynamically dispatched methods.
bool getBooleanOption(StringRef Name, bool DefaultVal, const ento::CheckerBase *C=nullptr, bool SearchInParents=false)
Interprets an option&#39;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.
bool naiveCTUEnabled()
Returns true when naive cross translation unit analysis is enabled.
Refers to destructors (implicit or explicit).
Dataflow Directional Tag Classes.
unsigned getGraphTrimInterval()
Returns how often nodes in the ExplodedGraph should be recycled to save memory.
StringRef getCTUIndexName()
Returns the name of the file containing the CTU index of functions.
ExplorationStrategyKind getExplorationStrategy()
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 includeImplicitDtorsInCFG()
Returns whether or not implicit destructors for C++ objects should be included in the CFG...
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.
bool shouldCrosscheckWithZ3()
Returns whether bug reports should be crosschecked with the Z3 constraint manager backend...
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&#39;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++ &#39;shared_ptr&#39; 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)