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" 29 using namespace clang;
33 std::vector<StringRef>
35 static const StringRef StaticAnalyzerChecks[] = {
37 #define CHECKER(FULLNAME, CLASS, DESCFILE, HELPTEXT, GROUPINDEX, HIDDEN) \ 39 #include "clang/StaticAnalyzer/Checkers/Checkers.inc" 43 std::vector<StringRef> Result;
44 for (StringRef
CheckName : StaticAnalyzerChecks) {
46 (IncludeExperimental || !
CheckName.startswith(
"alpha.")))
53 if (UserMode == UMK_NotSet) {
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)
60 assert(UserMode != UMK_NotSet &&
"User mode is invalid.");
67 if (ExplorationStrategy == ExplorationStrategyKind::NotSet) {
70 .insert(std::make_pair(
"exploration_strategy",
"unexplored_first_queue"))
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.");
86 return ExplorationStrategy;
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";
104 Config.insert(std::make_pair(
"ipa", DefaultIPA)).first->second;
105 IPAKind IPAConfig = llvm::StringSwitch<IPAKind>(ModeStr)
112 assert(IPAConfig !=
IPAK_NotSet &&
"IPA Mode is invalid.");
126 if (!CXXMemberInliningMode) {
127 static const char *ModeKey =
"c++-inlining";
130 Config.insert(std::make_pair(ModeKey,
"destructors")).first->second;
135 MutableMode = llvm::StringSwitch<CXXInlineableMemberKind>(ModeStr)
149 return CXXMemberInliningMode >= K;
152 static StringRef
toString(
bool b) {
return b ?
"true" :
"false"; }
154 StringRef AnalyzerOptions::getCheckerOption(StringRef CheckerName,
155 StringRef OptionName,
157 bool SearchInParents) {
160 ConfigTable::const_iterator E = Config.end();
162 ConfigTable::const_iterator I =
163 Config.find((Twine(CheckerName) +
":" + OptionName).str());
165 return StringRef(I->getValue());
166 size_t Pos = CheckerName.rfind(
'.');
167 if (Pos == StringRef::npos)
169 CheckerName = CheckerName.substr(0, Pos);
170 }
while (!CheckerName.empty() && SearchInParents);
176 bool SearchInParents) {
184 : StringRef(Config.insert(std::make_pair(Name, Default)).first->second);
185 return llvm::StringSwitch<bool>(V)
187 .Case(
"false",
false)
188 .Default(DefaultVal);
193 bool SearchInParents) {
195 V = getBooleanOption(Name, DefaultVal, C, SearchInParents);
200 return getBooleanOption(IncludeTemporaryDtorsInCFG,
201 "cfg-temporary-dtors",
206 return getBooleanOption(IncludeImplicitDtorsInCFG,
207 "cfg-implicit-dtors",
212 return getBooleanOption(IncludeLifetimeInCFG,
"cfg-lifetime",
217 return getBooleanOption(IncludeLoopExitInCFG,
"cfg-loopexit",
222 return getBooleanOption(IncludeRichConstructorsInCFG,
223 "cfg-rich-constructors",
228 return getBooleanOption(IncludeScopesInCFG,
234 return getBooleanOption(InlineCXXStandardLibrary,
235 "c++-stdlib-inlining",
240 return getBooleanOption(InlineTemplateFunctions,
241 "c++-template-inlining",
246 return getBooleanOption(InlineCXXAllocator,
247 "c++-allocator-inlining",
252 return getBooleanOption(InlineCXXContainerMethods,
253 "c++-container-inlining",
258 return getBooleanOption(InlineCXXSharedPtrDtor,
259 "c++-shared_ptr-inlining",
264 return getBooleanOption(InlineCXXTemporaryDtors,
265 "c++-temp-dtor-inlining",
270 return getBooleanOption(ObjCInliningMode,
276 return getBooleanOption(SuppressNullReturnPaths,
277 "suppress-null-return-paths",
282 return getBooleanOption(AvoidSuppressingNullArgumentPaths,
283 "avoid-suppressing-null-argument-paths",
288 return getBooleanOption(SuppressInlinedDefensiveChecks,
289 "suppress-inlined-defensive-checks",
294 return getBooleanOption(SuppressFromCXXStandardLibrary,
295 "suppress-c++-stdlib",
300 return getBooleanOption(CrosscheckWithZ3,
301 "crosscheck-with-z3",
306 return getBooleanOption(ReportIssuesInMainSourceFile,
307 "report-in-main-source-file",
313 return getBooleanOption(StableReportFilename,
314 "stable-report-filename",
319 return getBooleanOption(SerializeStats,
325 return getBooleanOption(ElideConstructors,
326 "elide-constructors",
332 bool SearchInParents) {
334 llvm::raw_svector_ostream OS(StrBuf);
339 : StringRef(Config.insert(std::make_pair(Name, OS.str()))
342 int Res = DefaultVal;
343 bool b = V.getAsInteger(10, Res);
344 assert(!b &&
"analyzer-config option should be numeric");
350 StringRef DefaultVal,
352 bool SearchInParents) {
356 Config.insert(std::make_pair(Name, DefaultVal)).first->second);
360 if (!AlwaysInlineSize.hasValue())
361 AlwaysInlineSize = getOptionAsInteger(
"ipa-always-inline-size", 3);
362 return AlwaysInlineSize.getValue();
366 if (!MaxInlinableSize.hasValue()) {
367 int DefaultValue = 0;
368 UserModeKind HighLevelMode = getUserMode();
369 switch (HighLevelMode) {
371 llvm_unreachable(
"Invalid mode.");
380 MaxInlinableSize = getOptionAsInteger(
"max-inlinable-size", DefaultValue);
382 return MaxInlinableSize.getValue();
386 if (!GraphTrimInterval.hasValue())
387 GraphTrimInterval = getOptionAsInteger(
"graph-trim-interval", 1000);
388 return GraphTrimInterval.getValue();
392 if (!MaxSymbolComplexity.hasValue())
393 MaxSymbolComplexity = getOptionAsInteger(
"max-symbol-complexity", 35);
394 return MaxSymbolComplexity.getValue();
398 if (!MaxTimesInlineLarge.hasValue())
399 MaxTimesInlineLarge = getOptionAsInteger(
"max-times-inline-large", 32);
400 return MaxTimesInlineLarge.getValue();
404 if (!MinCFGSizeTreatFunctionsAsLarge.hasValue())
405 MinCFGSizeTreatFunctionsAsLarge = getOptionAsInteger(
406 "min-cfg-size-treat-functions-as-large", 14);
407 return MinCFGSizeTreatFunctionsAsLarge.getValue();
411 if (!MaxNodesPerTopLevelFunction.hasValue()) {
412 int DefaultValue = 0;
413 UserModeKind HighLevelMode = getUserMode();
414 switch (HighLevelMode) {
416 llvm_unreachable(
"Invalid mode.");
418 DefaultValue = 75000;
421 DefaultValue = 225000;
424 MaxNodesPerTopLevelFunction = getOptionAsInteger(
"max-nodes", DefaultValue);
426 return MaxNodesPerTopLevelFunction.getValue();
430 return getBooleanOption(
"faux-bodies",
true);
434 return getBooleanOption(
"prune-paths",
true);
438 return getBooleanOption(
"cfg-conditional-static-initializers",
true);
442 if (!InlineLambdas.hasValue())
443 InlineLambdas = getBooleanOption(
"inline-lambdas",
true);
444 return InlineLambdas.getValue();
448 if (!WidenLoops.hasValue())
449 WidenLoops = getBooleanOption(
"widen-loops",
false);
450 return WidenLoops.getValue();
454 if (!UnrollLoops.hasValue())
455 UnrollLoops = getBooleanOption(
"unroll-loops",
false);
456 return UnrollLoops.getValue();
460 if (!DisplayNotesAsEvents.hasValue())
461 DisplayNotesAsEvents =
462 getBooleanOption(
"notes-as-events",
false);
463 return DisplayNotesAsEvents.getValue();
467 if (!AggressiveBinaryOperationSimplification.hasValue())
468 AggressiveBinaryOperationSimplification =
469 getBooleanOption(
"aggressive-binary-operation-simplification",
471 return AggressiveBinaryOperationSimplification.getValue();
475 if (!CTUDir.hasValue()) {
476 CTUDir = getOptionAsString(
"ctu-dir",
"");
477 if (!llvm::sys::fs::is_directory(*CTUDir))
480 return CTUDir.getValue();
484 if (!NaiveCTU.hasValue()) {
485 NaiveCTU = getBooleanOption(
"experimental-enable-naive-ctu-analysis",
488 return NaiveCTU.getValue();
492 if (!CTUIndexName.hasValue())
493 CTUIndexName = getOptionAsString(
"ctu-index-name",
"externalFnMap.txt");
494 return CTUIndexName.getValue();
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...
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 shouldAggressivelySimplifyBinaryOperation()
Returns true if SValBuilder should rearrange comparisons and additive operations of symbolic expressi...
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'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
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...
bool shouldUnrollLoops()
Returns true if the analysis should try to unroll loops with known bounds.
unsigned getMaxInlinableSize()
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 getAlwaysInlineSize()
unsigned getMaxNodesPerTopLevelFunction()
Returns the maximum number of nodes the analyzer can generate while exploring a top level function (f...
unsigned getMaxSymbolComplexity()
Returns the maximum complexity of symbolic constraint (50 by default).
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.
bool shouldSerializeStats()
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 shouldElideConstructors()
Returns true if elidable C++ copy-constructors and move-constructors should be actually elided during...
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'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)