1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" |
15 | #include "clang/StaticAnalyzer/Core/Checker.h" |
16 | #include "llvm/ADT/SmallString.h" |
17 | #include "llvm/ADT/StringSwitch.h" |
18 | #include "llvm/ADT/StringRef.h" |
19 | #include "llvm/ADT/Twine.h" |
20 | #include "llvm/Support/ErrorHandling.h" |
21 | #include "llvm/Support/FileSystem.h" |
22 | #include "llvm/Support/raw_ostream.h" |
23 | #include <cassert> |
24 | #include <cstddef> |
25 | #include <utility> |
26 | #include <vector> |
27 | |
28 | using namespace clang; |
29 | using namespace ento; |
30 | using namespace llvm; |
31 | |
32 | std::vector<StringRef> |
33 | AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental ) { |
34 | static const StringRef StaticAnalyzerChecks[] = { |
35 | #define GET_CHECKERS |
36 | #define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI) \ |
37 | FULLNAME, |
38 | #include "clang/StaticAnalyzer/Checkers/Checkers.inc" |
39 | #undef CHECKER |
40 | #undef GET_CHECKERS |
41 | }; |
42 | std::vector<StringRef> Result; |
43 | for (StringRef CheckName : StaticAnalyzerChecks) { |
44 | if (!CheckName.startswith("debug.") && |
45 | (IncludeExperimental || !CheckName.startswith("alpha."))) |
46 | Result.push_back(CheckName); |
47 | } |
48 | return Result; |
49 | } |
50 | |
51 | ExplorationStrategyKind |
52 | AnalyzerOptions::getExplorationStrategy() const { |
53 | auto K = |
54 | llvm::StringSwitch<llvm::Optional<ExplorationStrategyKind>>( |
55 | ExplorationStrategy) |
56 | .Case("dfs", ExplorationStrategyKind::DFS) |
57 | .Case("bfs", ExplorationStrategyKind::BFS) |
58 | .Case("unexplored_first", |
59 | ExplorationStrategyKind::UnexploredFirst) |
60 | .Case("unexplored_first_queue", |
61 | ExplorationStrategyKind::UnexploredFirstQueue) |
62 | .Case("unexplored_first_location_queue", |
63 | ExplorationStrategyKind::UnexploredFirstLocationQueue) |
64 | .Case("bfs_block_dfs_contents", |
65 | ExplorationStrategyKind::BFSBlockDFSContents) |
66 | .Default(None); |
67 | (0) . __assert_fail ("K.hasValue() && \"User mode is invalid.\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp", 67, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(K.hasValue() && "User mode is invalid."); |
68 | return K.getValue(); |
69 | } |
70 | |
71 | IPAKind AnalyzerOptions::getIPAMode() const { |
72 | auto K = llvm::StringSwitch<llvm::Optional<IPAKind>>(IPAMode) |
73 | .Case("none", IPAK_None) |
74 | .Case("basic-inlining", IPAK_BasicInlining) |
75 | .Case("inlining", IPAK_Inlining) |
76 | .Case("dynamic", IPAK_DynamicDispatch) |
77 | .Case("dynamic-bifurcate", IPAK_DynamicDispatchBifurcate) |
78 | .Default(None); |
79 | (0) . __assert_fail ("K.hasValue() && \"IPA Mode is invalid.\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp", 79, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(K.hasValue() && "IPA Mode is invalid."); |
80 | |
81 | return K.getValue(); |
82 | } |
83 | |
84 | bool |
85 | AnalyzerOptions::mayInlineCXXMemberFunction( |
86 | CXXInlineableMemberKind Param) const { |
87 | if (getIPAMode() < IPAK_Inlining) |
88 | return false; |
89 | |
90 | auto K = |
91 | llvm::StringSwitch<llvm::Optional<CXXInlineableMemberKind>>( |
92 | CXXMemberInliningMode) |
93 | .Case("constructors", CIMK_Constructors) |
94 | .Case("destructors", CIMK_Destructors) |
95 | .Case("methods", CIMK_MemberFunctions) |
96 | .Case("none", CIMK_None) |
97 | .Default(None); |
98 | |
99 | (0) . __assert_fail ("K.hasValue() && \"Invalid c++ member function inlining mode.\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp", 99, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(K.hasValue() && "Invalid c++ member function inlining mode."); |
100 | |
101 | return *K >= Param; |
102 | } |
103 | |
104 | StringRef AnalyzerOptions::getCheckerStringOption(StringRef CheckerName, |
105 | StringRef OptionName, |
106 | StringRef DefaultVal, |
107 | bool SearchInParents ) const { |
108 | (0) . __assert_fail ("!CheckerName.empty() && \"Empty checker name! Make sure the checker object (including it's \" \"bases!) if fully initialized before calling this function!\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp", 110, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!CheckerName.empty() && |
109 | (0) . __assert_fail ("!CheckerName.empty() && \"Empty checker name! Make sure the checker object (including it's \" \"bases!) if fully initialized before calling this function!\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp", 110, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "Empty checker name! Make sure the checker object (including it's " |
110 | (0) . __assert_fail ("!CheckerName.empty() && \"Empty checker name! Make sure the checker object (including it's \" \"bases!) if fully initialized before calling this function!\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp", 110, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "bases!) if fully initialized before calling this function!"); |
111 | |
112 | ConfigTable::const_iterator E = Config.end(); |
113 | do { |
114 | ConfigTable::const_iterator I = |
115 | Config.find((Twine(CheckerName) + ":" + OptionName).str()); |
116 | if (I != E) |
117 | return StringRef(I->getValue()); |
118 | size_t Pos = CheckerName.rfind('.'); |
119 | if (Pos == StringRef::npos) |
120 | return DefaultVal; |
121 | CheckerName = CheckerName.substr(0, Pos); |
122 | } while (!CheckerName.empty() && SearchInParents); |
123 | return DefaultVal; |
124 | } |
125 | |
126 | StringRef AnalyzerOptions::getCheckerStringOption(const ento::CheckerBase *C, |
127 | StringRef OptionName, |
128 | StringRef DefaultVal, |
129 | bool SearchInParents ) const { |
130 | return getCheckerStringOption( |
131 | C->getTagDescription(), OptionName, DefaultVal, SearchInParents); |
132 | } |
133 | |
134 | bool AnalyzerOptions::getCheckerBooleanOption(StringRef CheckerName, |
135 | StringRef OptionName, |
136 | bool DefaultVal, |
137 | bool SearchInParents ) const { |
138 | |
139 | |
140 | |
141 | return llvm::StringSwitch<bool>( |
142 | getCheckerStringOption(CheckerName, OptionName, |
143 | DefaultVal ? "true" : "false", |
144 | SearchInParents)) |
145 | .Case("true", true) |
146 | .Case("false", false) |
147 | .Default(DefaultVal); |
148 | } |
149 | |
150 | bool AnalyzerOptions::getCheckerBooleanOption(const ento::CheckerBase *C, |
151 | StringRef OptionName, |
152 | bool DefaultVal, |
153 | bool SearchInParents ) const { |
154 | return getCheckerBooleanOption( |
155 | C->getTagDescription(), OptionName, DefaultVal, SearchInParents); |
156 | } |
157 | |
158 | int AnalyzerOptions::getCheckerIntegerOption(StringRef CheckerName, |
159 | StringRef OptionName, |
160 | int DefaultVal, |
161 | bool SearchInParents ) const { |
162 | int Ret = DefaultVal; |
163 | bool HasFailed = getCheckerStringOption(CheckerName, OptionName, |
164 | std::to_string(DefaultVal), |
165 | SearchInParents) |
166 | .getAsInteger(10, Ret); |
167 | (0) . __assert_fail ("!HasFailed && \"analyzer-config option should be numeric\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp", 167, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!HasFailed && "analyzer-config option should be numeric"); |
168 | (void)HasFailed; |
169 | return Ret; |
170 | } |
171 | |
172 | int AnalyzerOptions::getCheckerIntegerOption(const ento::CheckerBase *C, |
173 | StringRef OptionName, |
174 | int DefaultVal, |
175 | bool SearchInParents ) const { |
176 | return getCheckerIntegerOption( |
177 | C->getTagDescription(), OptionName, DefaultVal, SearchInParents); |
178 | } |
179 | |