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 15 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 16 #include "clang/StaticAnalyzer/Core/Checker.h" 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, HELPTEXT, DOC_URI) \ 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 ExplorationStrategyKind 53 AnalyzerOptions::getExplorationStrategy() const { 54 auto K = 55 llvm::StringSwitch<llvm::Optional<ExplorationStrategyKind>>( 56 ExplorationStrategy) 57 .Case("dfs", ExplorationStrategyKind::DFS) 58 .Case("bfs", ExplorationStrategyKind::BFS) 59 .Case("unexplored_first", 60 ExplorationStrategyKind::UnexploredFirst) 61 .Case("unexplored_first_queue", 62 ExplorationStrategyKind::UnexploredFirstQueue) 63 .Case("unexplored_first_location_queue", 64 ExplorationStrategyKind::UnexploredFirstLocationQueue) 65 .Case("bfs_block_dfs_contents", 66 ExplorationStrategyKind::BFSBlockDFSContents) 67 .Default(None); 68 assert(K.hasValue() && "User mode is invalid."); 69 return K.getValue(); 70 } 71 72 IPAKind AnalyzerOptions::getIPAMode() const { 73 auto K = llvm::StringSwitch<llvm::Optional<IPAKind>>(IPAMode) 74 .Case("none", IPAK_None) 75 .Case("basic-inlining", IPAK_BasicInlining) 76 .Case("inlining", IPAK_Inlining) 77 .Case("dynamic", IPAK_DynamicDispatch) 78 .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate) 79 .Default(None); 80 assert(K.hasValue() && "IPA Mode is invalid."); 81 82 return K.getValue(); 83 } 84 85 bool 86 AnalyzerOptions::mayInlineCXXMemberFunction( 87 CXXInlineableMemberKind Param) const { 88 if (getIPAMode() < IPAK_Inlining) 89 return false; 90 91 auto K = 92 llvm::StringSwitch<llvm::Optional<CXXInlineableMemberKind>>( 93 CXXMemberInliningMode) 94 .Case("constructors", CIMK_Constructors) 95 .Case("destructors", CIMK_Destructors) 96 .Case("methods", CIMK_MemberFunctions) 97 .Case("none", CIMK_None) 98 .Default(None); 99 100 assert(K.hasValue() && "Invalid c++ member function inlining mode."); 101 102 return *K >= Param; 103 } 104 105 StringRef AnalyzerOptions::getCheckerStringOption(StringRef OptionName, 106 StringRef DefaultVal, 107 const CheckerBase *C, 108 bool SearchInParents) const { 109 assert(C); 110 // Search for a package option if the option for the checker is not specified 111 // and search in parents is enabled. 112 StringRef CheckerName = C->getTagDescription(); 113 114 assert(!CheckerName.empty() && 115 "Empty checker name! Make sure the checker object (including it's " 116 "bases!) if fully initialized before calling this function!"); 117 ConfigTable::const_iterator E = Config.end(); 118 do { 119 ConfigTable::const_iterator I = 120 Config.find((Twine(CheckerName) + ":" + OptionName).str()); 121 if (I != E) 122 return StringRef(I->getValue()); 123 size_t Pos = CheckerName.rfind('.'); 124 if (Pos == StringRef::npos) 125 return DefaultVal; 126 CheckerName = CheckerName.substr(0, Pos); 127 } while (!CheckerName.empty() && SearchInParents); 128 return DefaultVal; 129 } 130 131 bool AnalyzerOptions::getCheckerBooleanOption(StringRef Name, bool DefaultVal, 132 const CheckerBase *C, 133 bool SearchInParents) const { 134 // FIXME: We should emit a warning here if the value is something other than 135 // "true", "false", or the empty string (meaning the default value), 136 // but the AnalyzerOptions doesn't have access to a diagnostic engine. 137 assert(C); 138 return llvm::StringSwitch<bool>( 139 getCheckerStringOption(Name, DefaultVal ? "true" : "false", C, 140 SearchInParents)) 141 .Case("true", true) 142 .Case("false", false) 143 .Default(DefaultVal); 144 } 145 146 int AnalyzerOptions::getCheckerIntegerOption(StringRef Name, int DefaultVal, 147 const CheckerBase *C, 148 bool SearchInParents) const { 149 int Ret = DefaultVal; 150 bool HasFailed = getCheckerStringOption(Name, std::to_string(DefaultVal), C, 151 SearchInParents) 152 .getAsInteger(10, Ret); 153 assert(!HasFailed && "analyzer-config option should be numeric"); 154 (void)HasFailed; 155 return Ret; 156 } 157