clang  6.0.0svn
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 std::vector<StringRef>
27 AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental /* = false */) {
28  static const StringRef StaticAnalyzerChecks[] = {
29 #define GET_CHECKERS
30 #define CHECKER(FULLNAME, CLASS, DESCFILE, HELPTEXT, GROUPINDEX, HIDDEN) \
31  FULLNAME,
32 #include "clang/StaticAnalyzer/Checkers/Checkers.inc"
33 #undef CHECKER
34 #undef GET_CHECKERS
35  };
36  std::vector<StringRef> Result;
37  for (StringRef CheckName : StaticAnalyzerChecks) {
38  if (!CheckName.startswith("debug.") &&
39  (IncludeExperimental || !CheckName.startswith("alpha.")))
40  Result.push_back(CheckName);
41  }
42  return Result;
43 }
44 
45 AnalyzerOptions::UserModeKind AnalyzerOptions::getUserMode() {
46  if (UserMode == UMK_NotSet) {
47  StringRef ModeStr =
48  Config.insert(std::make_pair("mode", "deep")).first->second;
49  UserMode = llvm::StringSwitch<UserModeKind>(ModeStr)
50  .Case("shallow", UMK_Shallow)
51  .Case("deep", UMK_Deep)
52  .Default(UMK_NotSet);
53  assert(UserMode != UMK_NotSet && "User mode is invalid.");
54  }
55  return UserMode;
56 }
57 
59  if (IPAMode == IPAK_NotSet) {
60 
61  // Use the User Mode to set the default IPA value.
62  // Note, we have to add the string to the Config map for the ConfigDumper
63  // checker to function properly.
64  const char *DefaultIPA = nullptr;
65  UserModeKind HighLevelMode = getUserMode();
66  if (HighLevelMode == UMK_Shallow)
67  DefaultIPA = "inlining";
68  else if (HighLevelMode == UMK_Deep)
69  DefaultIPA = "dynamic-bifurcate";
70  assert(DefaultIPA);
71 
72  // Lookup the ipa configuration option, use the default from User Mode.
73  StringRef ModeStr =
74  Config.insert(std::make_pair("ipa", DefaultIPA)).first->second;
75  IPAKind IPAConfig = llvm::StringSwitch<IPAKind>(ModeStr)
76  .Case("none", IPAK_None)
77  .Case("basic-inlining", IPAK_BasicInlining)
78  .Case("inlining", IPAK_Inlining)
79  .Case("dynamic", IPAK_DynamicDispatch)
80  .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate)
81  .Default(IPAK_NotSet);
82  assert(IPAConfig != IPAK_NotSet && "IPA Mode is invalid.");
83 
84  // Set the member variable.
85  IPAMode = IPAConfig;
86  }
87 
88  return IPAMode;
89 }
90 
91 bool
93  if (getIPAMode() < IPAK_Inlining)
94  return false;
95 
96  if (!CXXMemberInliningMode) {
97  static const char *ModeKey = "c++-inlining";
98 
99  StringRef ModeStr =
100  Config.insert(std::make_pair(ModeKey, "destructors")).first->second;
101 
102  CXXInlineableMemberKind &MutableMode =
103  const_cast<CXXInlineableMemberKind &>(CXXMemberInliningMode);
104 
105  MutableMode = llvm::StringSwitch<CXXInlineableMemberKind>(ModeStr)
106  .Case("constructors", CIMK_Constructors)
107  .Case("destructors", CIMK_Destructors)
108  .Case("none", CIMK_None)
109  .Case("methods", CIMK_MemberFunctions)
110  .Default(CXXInlineableMemberKind());
111 
112  if (!MutableMode) {
113  // FIXME: We should emit a warning here about an unknown inlining kind,
114  // but the AnalyzerOptions doesn't have access to a diagnostic engine.
115  MutableMode = CIMK_None;
116  }
117  }
118 
119  return CXXMemberInliningMode >= K;
120 }
121 
122 static StringRef toString(bool b) { return b ? "true" : "false"; }
123 
124 StringRef AnalyzerOptions::getCheckerOption(StringRef CheckerName,
125  StringRef OptionName,
126  StringRef Default,
127  bool SearchInParents) {
128  // Search for a package option if the option for the checker is not specified
129  // and search in parents is enabled.
130  ConfigTable::const_iterator E = Config.end();
131  do {
132  ConfigTable::const_iterator I =
133  Config.find((Twine(CheckerName) + ":" + OptionName).str());
134  if (I != E)
135  return StringRef(I->getValue());
136  size_t Pos = CheckerName.rfind('.');
137  if (Pos == StringRef::npos)
138  return Default;
139  CheckerName = CheckerName.substr(0, Pos);
140  } while (!CheckerName.empty() && SearchInParents);
141  return Default;
142 }
143 
144 bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal,
145  const CheckerBase *C,
146  bool SearchInParents) {
147  // FIXME: We should emit a warning here if the value is something other than
148  // "true", "false", or the empty string (meaning the default value),
149  // but the AnalyzerOptions doesn't have access to a diagnostic engine.
150  StringRef Default = toString(DefaultVal);
151  StringRef V =
152  C ? getCheckerOption(C->getTagDescription(), Name, Default,
153  SearchInParents)
154  : StringRef(Config.insert(std::make_pair(Name, Default)).first->second);
155  return llvm::StringSwitch<bool>(V)
156  .Case("true", true)
157  .Case("false", false)
158  .Default(DefaultVal);
159 }
160 
162  bool DefaultVal, const CheckerBase *C,
163  bool SearchInParents) {
164  if (!V.hasValue())
165  V = getBooleanOption(Name, DefaultVal, C, SearchInParents);
166  return V.getValue();
167 }
168 
170  return getBooleanOption(IncludeTemporaryDtorsInCFG,
171  "cfg-temporary-dtors",
172  /* Default = */ false);
173 }
174 
176  return getBooleanOption(IncludeImplicitDtorsInCFG,
177  "cfg-implicit-dtors",
178  /* Default = */ true);
179 }
180 
182  return getBooleanOption(IncludeLifetimeInCFG, "cfg-lifetime",
183  /* Default = */ false);
184 }
185 
187  return getBooleanOption(IncludeLoopExitInCFG, "cfg-loopexit",
188  /* Default = */ false);
189 }
190 
192  return getBooleanOption(InlineCXXStandardLibrary,
193  "c++-stdlib-inlining",
194  /*Default=*/true);
195 }
196 
198  return getBooleanOption(InlineTemplateFunctions,
199  "c++-template-inlining",
200  /*Default=*/true);
201 }
202 
204  return getBooleanOption(InlineCXXAllocator,
205  "c++-allocator-inlining",
206  /*Default=*/false);
207 }
208 
210  return getBooleanOption(InlineCXXContainerMethods,
211  "c++-container-inlining",
212  /*Default=*/false);
213 }
214 
216  return getBooleanOption(InlineCXXSharedPtrDtor,
217  "c++-shared_ptr-inlining",
218  /*Default=*/false);
219 }
220 
221 
223  return getBooleanOption(ObjCInliningMode,
224  "objc-inlining",
225  /* Default = */ true);
226 }
227 
229  return getBooleanOption(SuppressNullReturnPaths,
230  "suppress-null-return-paths",
231  /* Default = */ true);
232 }
233 
235  return getBooleanOption(AvoidSuppressingNullArgumentPaths,
236  "avoid-suppressing-null-argument-paths",
237  /* Default = */ false);
238 }
239 
241  return getBooleanOption(SuppressInlinedDefensiveChecks,
242  "suppress-inlined-defensive-checks",
243  /* Default = */ true);
244 }
245 
247  return getBooleanOption(SuppressFromCXXStandardLibrary,
248  "suppress-c++-stdlib",
249  /* Default = */ true);
250 }
251 
253  return getBooleanOption(ReportIssuesInMainSourceFile,
254  "report-in-main-source-file",
255  /* Default = */ false);
256 }
257 
258 
260  return getBooleanOption(StableReportFilename,
261  "stable-report-filename",
262  /* Default = */ false);
263 }
264 
265 int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal,
266  const CheckerBase *C,
267  bool SearchInParents) {
268  SmallString<10> StrBuf;
269  llvm::raw_svector_ostream OS(StrBuf);
270  OS << DefaultVal;
271 
272  StringRef V = C ? getCheckerOption(C->getTagDescription(), Name, OS.str(),
273  SearchInParents)
274  : StringRef(Config.insert(std::make_pair(Name, OS.str()))
275  .first->second);
276 
277  int Res = DefaultVal;
278  bool b = V.getAsInteger(10, Res);
279  assert(!b && "analyzer-config option should be numeric");
280  (void)b;
281  return Res;
282 }
283 
284 StringRef AnalyzerOptions::getOptionAsString(StringRef Name,
285  StringRef DefaultVal,
286  const CheckerBase *C,
287  bool SearchInParents) {
288  return C ? getCheckerOption(C->getTagDescription(), Name, DefaultVal,
289  SearchInParents)
290  : StringRef(
291  Config.insert(std::make_pair(Name, DefaultVal)).first->second);
292 }
293 
295  if (!AlwaysInlineSize.hasValue())
296  AlwaysInlineSize = getOptionAsInteger("ipa-always-inline-size", 3);
297  return AlwaysInlineSize.getValue();
298 }
299 
301  if (!MaxInlinableSize.hasValue()) {
302 
303  int DefaultValue = 0;
304  UserModeKind HighLevelMode = getUserMode();
305  switch (HighLevelMode) {
306  default:
307  llvm_unreachable("Invalid mode.");
308  case UMK_Shallow:
309  DefaultValue = 4;
310  break;
311  case UMK_Deep:
312  DefaultValue = 100;
313  break;
314  }
315 
316  MaxInlinableSize = getOptionAsInteger("max-inlinable-size", DefaultValue);
317  }
318  return MaxInlinableSize.getValue();
319 }
320 
322  if (!GraphTrimInterval.hasValue())
323  GraphTrimInterval = getOptionAsInteger("graph-trim-interval", 1000);
324  return GraphTrimInterval.getValue();
325 }
326 
328  if (!MaxTimesInlineLarge.hasValue())
329  MaxTimesInlineLarge = getOptionAsInteger("max-times-inline-large", 32);
330  return MaxTimesInlineLarge.getValue();
331 }
332 
334  if (!MinCFGSizeTreatFunctionsAsLarge.hasValue())
335  MinCFGSizeTreatFunctionsAsLarge = getOptionAsInteger(
336  "min-cfg-size-treat-functions-as-large", 14);
337  return MinCFGSizeTreatFunctionsAsLarge.getValue();
338 }
339 
341  if (!MaxNodesPerTopLevelFunction.hasValue()) {
342  int DefaultValue = 0;
343  UserModeKind HighLevelMode = getUserMode();
344  switch (HighLevelMode) {
345  default:
346  llvm_unreachable("Invalid mode.");
347  case UMK_Shallow:
348  DefaultValue = 75000;
349  break;
350  case UMK_Deep:
351  DefaultValue = 225000;
352  break;
353  }
354  MaxNodesPerTopLevelFunction = getOptionAsInteger("max-nodes", DefaultValue);
355  }
356  return MaxNodesPerTopLevelFunction.getValue();
357 }
358 
360  return getBooleanOption("faux-bodies", true);
361 }
362 
364  return getBooleanOption("prune-paths", true);
365 }
366 
368  return getBooleanOption("cfg-conditional-static-initializers", true);
369 }
370 
372  if (!InlineLambdas.hasValue())
373  InlineLambdas = getBooleanOption("inline-lambdas", /*Default=*/true);
374  return InlineLambdas.getValue();
375 }
376 
378  if (!WidenLoops.hasValue())
379  WidenLoops = getBooleanOption("widen-loops", /*Default=*/false);
380  return WidenLoops.getValue();
381 }
382 
384  if (!UnrollLoops.hasValue())
385  UnrollLoops = getBooleanOption("unroll-loops", /*Default=*/false);
386  return UnrollLoops.getValue();
387 }
388 
390  if (!DisplayNotesAsEvents.hasValue())
391  DisplayNotesAsEvents =
392  getBooleanOption("notes-as-events", /*Default=*/false);
393  return DisplayNotesAsEvents.getValue();
394 }
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:26
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.
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).
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.
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.
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.
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)