clang  5.0.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 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(InlineCXXStandardLibrary,
188  "c++-stdlib-inlining",
189  /*Default=*/true);
190 }
191 
193  return getBooleanOption(InlineTemplateFunctions,
194  "c++-template-inlining",
195  /*Default=*/true);
196 }
197 
199  return getBooleanOption(InlineCXXAllocator,
200  "c++-allocator-inlining",
201  /*Default=*/false);
202 }
203 
205  return getBooleanOption(InlineCXXContainerMethods,
206  "c++-container-inlining",
207  /*Default=*/false);
208 }
209 
211  return getBooleanOption(InlineCXXSharedPtrDtor,
212  "c++-shared_ptr-inlining",
213  /*Default=*/false);
214 }
215 
216 
218  return getBooleanOption(ObjCInliningMode,
219  "objc-inlining",
220  /* Default = */ true);
221 }
222 
224  return getBooleanOption(SuppressNullReturnPaths,
225  "suppress-null-return-paths",
226  /* Default = */ true);
227 }
228 
230  return getBooleanOption(AvoidSuppressingNullArgumentPaths,
231  "avoid-suppressing-null-argument-paths",
232  /* Default = */ false);
233 }
234 
236  return getBooleanOption(SuppressInlinedDefensiveChecks,
237  "suppress-inlined-defensive-checks",
238  /* Default = */ true);
239 }
240 
242  return getBooleanOption(SuppressFromCXXStandardLibrary,
243  "suppress-c++-stdlib",
244  /* Default = */ true);
245 }
246 
248  return getBooleanOption(ReportIssuesInMainSourceFile,
249  "report-in-main-source-file",
250  /* Default = */ false);
251 }
252 
253 
255  return getBooleanOption(StableReportFilename,
256  "stable-report-filename",
257  /* Default = */ false);
258 }
259 
260 int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal,
261  const CheckerBase *C,
262  bool SearchInParents) {
263  SmallString<10> StrBuf;
264  llvm::raw_svector_ostream OS(StrBuf);
265  OS << DefaultVal;
266 
267  StringRef V = C ? getCheckerOption(C->getTagDescription(), Name, OS.str(),
268  SearchInParents)
269  : StringRef(Config.insert(std::make_pair(Name, OS.str()))
270  .first->second);
271 
272  int Res = DefaultVal;
273  bool b = V.getAsInteger(10, Res);
274  assert(!b && "analyzer-config option should be numeric");
275  (void)b;
276  return Res;
277 }
278 
280  StringRef DefaultVal,
281  const CheckerBase *C,
282  bool SearchInParents) {
283  return C ? getCheckerOption(C->getTagDescription(), Name, DefaultVal,
284  SearchInParents)
285  : StringRef(
286  Config.insert(std::make_pair(Name, DefaultVal)).first->second);
287 }
288 
290  if (!AlwaysInlineSize.hasValue())
291  AlwaysInlineSize = getOptionAsInteger("ipa-always-inline-size", 3);
292  return AlwaysInlineSize.getValue();
293 }
294 
296  if (!MaxInlinableSize.hasValue()) {
297 
298  int DefaultValue = 0;
299  UserModeKind HighLevelMode = getUserMode();
300  switch (HighLevelMode) {
301  default:
302  llvm_unreachable("Invalid mode.");
303  case UMK_Shallow:
304  DefaultValue = 4;
305  break;
306  case UMK_Deep:
307  DefaultValue = 100;
308  break;
309  }
310 
311  MaxInlinableSize = getOptionAsInteger("max-inlinable-size", DefaultValue);
312  }
313  return MaxInlinableSize.getValue();
314 }
315 
317  if (!GraphTrimInterval.hasValue())
318  GraphTrimInterval = getOptionAsInteger("graph-trim-interval", 1000);
319  return GraphTrimInterval.getValue();
320 }
321 
323  if (!MaxTimesInlineLarge.hasValue())
324  MaxTimesInlineLarge = getOptionAsInteger("max-times-inline-large", 32);
325  return MaxTimesInlineLarge.getValue();
326 }
327 
329  if (!MinCFGSizeTreatFunctionsAsLarge.hasValue())
330  MinCFGSizeTreatFunctionsAsLarge = getOptionAsInteger(
331  "min-cfg-size-treat-functions-as-large", 14);
332  return MinCFGSizeTreatFunctionsAsLarge.getValue();
333 }
334 
336  if (!MaxNodesPerTopLevelFunction.hasValue()) {
337  int DefaultValue = 0;
338  UserModeKind HighLevelMode = getUserMode();
339  switch (HighLevelMode) {
340  default:
341  llvm_unreachable("Invalid mode.");
342  case UMK_Shallow:
343  DefaultValue = 75000;
344  break;
345  case UMK_Deep:
346  DefaultValue = 225000;
347  break;
348  }
349  MaxNodesPerTopLevelFunction = getOptionAsInteger("max-nodes", DefaultValue);
350  }
351  return MaxNodesPerTopLevelFunction.getValue();
352 }
353 
355  return getBooleanOption("faux-bodies", true);
356 }
357 
359  return getBooleanOption("prune-paths", true);
360 }
361 
363  return getBooleanOption("cfg-conditional-static-initializers", true);
364 }
365 
367  if (!InlineLambdas.hasValue())
368  InlineLambdas = getBooleanOption("inline-lambdas", /*Default=*/true);
369  return InlineLambdas.getValue();
370 }
371 
373  if (!WidenLoops.hasValue())
374  WidenLoops = getBooleanOption("widen-loops", /*Default=*/false);
375  return WidenLoops.getValue();
376 }
377 
379  if (!DisplayNotesAsEvents.hasValue())
380  DisplayNotesAsEvents =
381  getBooleanOption("notes-as-events", /*Default=*/false);
382  return DisplayNotesAsEvents.getValue();
383 }
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.
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'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.
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 '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).
StringRef Name
Definition: USRFinder.cpp:123
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 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'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.
const NamedDecl * Result
Definition: USRFinder.cpp:70
static StringRef toString(bool b)