1 //===- AnalyzerOptions.h - Analysis Engine Options --------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This header defines various options for the static analyzer that are set
10 // by the frontend and are consulted throughout the analyzer.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
15 #define LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
16 
17 #include "clang/Basic/LLVM.h"
18 #include "llvm/ADT/IntrusiveRefCntPtr.h"
19 #include "llvm/ADT/Optional.h"
20 #include "llvm/ADT/StringMap.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/ADT/StringSwitch.h"
23 #include <string>
24 #include <utility>
25 #include <vector>
26 
27 namespace clang {
28 
29 namespace ento {
30 
31 class CheckerBase;
32 
33 } // namespace ento
34 
35 /// Analysis - Set of available source code analyses.
36 enum Analyses {
37 #define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) NAME,
38 #include "clang/StaticAnalyzer/Core/Analyses.def"
39 NumAnalyses
40 };
41 
42 /// AnalysisStores - Set of available analysis store models.
43 enum AnalysisStores {
44 #define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) NAME##Model,
45 #include "clang/StaticAnalyzer/Core/Analyses.def"
46 NumStores
47 };
48 
49 /// AnalysisConstraints - Set of available constraint models.
50 enum AnalysisConstraints {
51 #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) NAME##Model,
52 #include "clang/StaticAnalyzer/Core/Analyses.def"
53 NumConstraints
54 };
55 
56 /// AnalysisDiagClients - Set of available diagnostic clients for rendering
57 ///  analysis results.
58 enum AnalysisDiagClients {
59 #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) PD_##NAME,
60 #include "clang/StaticAnalyzer/Core/Analyses.def"
61 PD_NONE,
62 NUM_ANALYSIS_DIAG_CLIENTS
63 };
64 
65 /// AnalysisPurgeModes - Set of available strategies for dead symbol removal.
66 enum AnalysisPurgeMode {
67 #define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) NAME,
68 #include "clang/StaticAnalyzer/Core/Analyses.def"
69 NumPurgeModes
70 };
71 
72 /// AnalysisInlineFunctionSelection - Set of inlining function selection heuristics.
73 enum AnalysisInliningMode {
74 #define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) NAME,
75 #include "clang/StaticAnalyzer/Core/Analyses.def"
76 NumInliningModes
77 };
78 
79 /// Describes the different kinds of C++ member functions which can be
80 /// considered for inlining by the analyzer.
81 ///
82 /// These options are cumulative; enabling one kind of member function will
83 /// enable all kinds with lower enum values.
84 enum CXXInlineableMemberKind {
85   // Uninitialized = 0,
86 
87   /// A dummy mode in which no C++ inlining is enabled.
88   CIMK_None,
89 
90   /// Refers to regular member function and operator calls.
91   CIMK_MemberFunctions,
92 
93   /// Refers to constructors (implicit or explicit).
94   ///
95   /// Note that a constructor will not be inlined if the corresponding
96   /// destructor is non-trivial.
97   CIMK_Constructors,
98 
99   /// Refers to destructors (implicit or explicit).
100   CIMK_Destructors
101 };
102 
103 /// Describes the different modes of inter-procedural analysis.
104 enum IPAKind {
105   /// Perform only intra-procedural analysis.
106   IPAK_None = 1,
107 
108   /// Inline C functions and blocks when their definitions are available.
109   IPAK_BasicInlining = 2,
110 
111   /// Inline callees(C, C++, ObjC) when their definitions are available.
112   IPAK_Inlining = 3,
113 
114   /// Enable inlining of dynamically dispatched methods.
115   IPAK_DynamicDispatch = 4,
116 
117   /// Enable inlining of dynamically dispatched methods, bifurcate paths when
118   /// exact type info is unavailable.
119   IPAK_DynamicDispatchBifurcate = 5
120 };
121 
122 enum class ExplorationStrategyKind {
123   DFS,
124   BFS,
125   UnexploredFirst,
126   UnexploredFirstQueue,
127   UnexploredFirstLocationQueue,
128   BFSBlockDFSContents,
129 };
130 
131 /// Describes the kinds for high-level analyzer mode.
132 enum UserModeKind {
133   /// Perform shallow but fast analyzes.
134   UMK_Shallow = 1,
135 
136   /// Perform deep analyzes.
137   UMK_Deep = 2
138 };
139 
140 /// Stores options for the analyzer from the command line.
141 ///
142 /// Some options are frontend flags (e.g.: -analyzer-output), but some are
143 /// analyzer configuration options, which are preceded by -analyzer-config
144 /// (e.g.: -analyzer-config notes-as-events=true).
145 ///
146 /// If you'd like to add a new frontend flag, add it to
147 /// include/clang/Driver/CC1Options.td, add a new field to store the value of
148 /// that flag in this class, and initialize it in
149 /// lib/Frontend/CompilerInvocation.cpp.
150 ///
151 /// If you'd like to add a new non-checker configuration, register it in
152 /// include/clang/StaticAnalyzer/Core/AnalyzerOptions.def, and refer to the
153 /// top of the file for documentation.
154 ///
155 /// If you'd like to add a new checker option, call getChecker*Option()
156 /// whenever.
157 ///
158 /// Some of the options are controlled by raw frontend flags for no good reason,
159 /// and should be eventually converted into -analyzer-config flags. New analyzer
160 /// options should not be implemented as frontend flags. Frontend flags still
161 /// make sense for things that do not affect the actual analysis.
162 class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
163 public:
164   using ConfigTable = llvm::StringMap<std::string>;
165 
166   /// Retrieves the list of checkers generated from Checkers.td. This doesn't
167   /// contain statically linked but non-generated checkers and plugin checkers!
168   static std::vector<StringRef>
169   getRegisteredCheckers(bool IncludeExperimental = false);
170 
171   /// Retrieves the list of packages generated from Checkers.td. This doesn't
172   /// contain statically linked but non-generated packages and plugin packages!
173   static std::vector<StringRef>
174   getRegisteredPackages(bool IncludeExperimental = false);
175 
176   /// Convenience function for printing options or checkers and their
177   /// description in a formatted manner. If \p MinLineWidth is set to 0, no line
178   /// breaks are introduced for the description.
179   ///
180   /// Format, depending whether the option name's length is less then
181   /// \p OptionWidth:
182   ///
183   ///   <padding>EntryName<padding>Description
184   ///   <---------padding--------->Description
185   ///   <---------padding--------->Description
186   ///
187   ///   <padding>VeryVeryLongOptionName
188   ///   <---------padding--------->Description
189   ///   <---------padding--------->Description
190   ///   ^~~~~~~~ InitialPad
191   ///   ^~~~~~~~~~~~~~~~~~~~~~~~~~ EntryWidth
192   ///   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~MinLineWidth
193   static void printFormattedEntry(
194       llvm::raw_ostream &Out,
195       std::pair<StringRef, StringRef> EntryDescPair,
196       size_t EntryWidth, size_t InitialPad, size_t MinLineWidth = 0);
197 
198   /// Pairs of checker/package name and enable/disable.
199   std::vector<std::pair<std::string, bool>> CheckersAndPackages;
200 
201   /// Vector of checker/package names which will not emit warnings.
202   std::vector<std::string> SilencedCheckersAndPackages;
203 
204   /// A key-value table of use-specified configuration values.
205   // TODO: This shouldn't be public.
206   ConfigTable Config;
207   AnalysisStores AnalysisStoreOpt = RegionStoreModel;
208   AnalysisConstraints AnalysisConstraintsOpt = RangeConstraintsModel;
209   AnalysisDiagClients AnalysisDiagOpt = PD_HTML;
210   AnalysisPurgeMode AnalysisPurgeOpt = PurgeStmt;
211 
212   std::string AnalyzeSpecificFunction;
213 
214   /// File path to which the exploded graph should be dumped.
215   std::string DumpExplodedGraphTo;
216 
217   /// Store full compiler invocation for reproducible instructions in the
218   /// generated report.
219   std::string FullCompilerInvocation;
220 
221   /// The maximum number of times the analyzer visits a block.
222   unsigned maxBlockVisitOnPath;
223 
224   /// Disable all analyzer checkers.
225   ///
226   /// This flag allows one to disable analyzer checkers on the code processed by
227   /// the given analysis consumer. Note, the code will get parsed and the
228   /// command-line options will get checked.
229   unsigned DisableAllCheckers : 1;
230 
231   unsigned ShowCheckerHelp : 1;
232   unsigned ShowCheckerHelpAlpha : 1;
233   unsigned ShowCheckerHelpDeveloper : 1;
234 
235   unsigned ShowCheckerOptionList : 1;
236   unsigned ShowCheckerOptionAlphaList : 1;
237   unsigned ShowCheckerOptionDeveloperList : 1;
238 
239   unsigned ShowEnabledCheckerList : 1;
240   unsigned ShowConfigOptionsList : 1;
241   unsigned ShouldEmitErrorsOnInvalidConfigValue : 1;
242   unsigned AnalyzeAll : 1;
243   unsigned AnalyzerDisplayProgress : 1;
244   unsigned AnalyzeNestedBlocks : 1;
245 
246   unsigned eagerlyAssumeBinOpBifurcation : 1;
247 
248   unsigned TrimGraph : 1;
249   unsigned visualizeExplodedGraphWithGraphViz : 1;
250   unsigned UnoptimizedCFG : 1;
251   unsigned PrintStats : 1;
252 
253   /// Do not re-analyze paths leading to exhausted nodes with a different
254   /// strategy. We get better code coverage when retry is enabled.
255   unsigned NoRetryExhausted : 1;
256 
257   /// Emit analyzer warnings as errors.
258   unsigned AnalyzerWerror : 1;
259 
260   /// The inlining stack depth limit.
261   // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls).
262   unsigned InlineMaxStackDepth = 5;
263 
264   /// The mode of function selection used during inlining.
265   AnalysisInliningMode InliningMode = NoRedundancy;
266 
267   // Create a field for each -analyzer-config option.
268 #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC,        \
269                                              SHALLOW_VAL, DEEP_VAL)            \
270   ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL)
271 
272 #define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)                \
273   TYPE NAME;
274 
275 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
276 #undef ANALYZER_OPTION
277 #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
278 
279   // Create an array of all -analyzer-config command line options. Sort it in
280   // the constructor.
281   std::vector<llvm::StringLiteral> AnalyzerConfigCmdFlags = {
282 #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC,        \
283                                              SHALLOW_VAL, DEEP_VAL)            \
284   ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL)
285 
286 #define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)                \
287   llvm::StringLiteral(CMDFLAG),
288 
289 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
290 #undef ANALYZER_OPTION
291 #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
292   };
293 
294   bool isUnknownAnalyzerConfig(StringRef Name) const {
295 
296     assert(std::is_sorted(AnalyzerConfigCmdFlags.begin(),
297                           AnalyzerConfigCmdFlags.end()));
298 
299     return !std::binary_search(AnalyzerConfigCmdFlags.begin(),
300                                AnalyzerConfigCmdFlags.end(), Name);
301   }
302 
303   AnalyzerOptions()
304       : DisableAllCheckers(false), ShowCheckerHelp(false),
305         ShowCheckerHelpAlpha(false), ShowCheckerHelpDeveloper(false),
306         ShowCheckerOptionList(false), ShowCheckerOptionAlphaList(false),
307         ShowCheckerOptionDeveloperList(false), ShowEnabledCheckerList(false),
308         ShowConfigOptionsList(false), AnalyzeAll(false),
309         AnalyzerDisplayProgress(false), AnalyzeNestedBlocks(false),
310         eagerlyAssumeBinOpBifurcation(false), TrimGraph(false),
311         visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false),
312         PrintStats(false), NoRetryExhausted(false), AnalyzerWerror(false) {
313     llvm::sort(AnalyzerConfigCmdFlags);
314   }
315 
316   /// Interprets an option's string value as a boolean. The "true" string is
317   /// interpreted as true and the "false" string is interpreted as false.
318   ///
319   /// If an option value is not provided, returns the given \p DefaultVal.
320   /// @param [in] CheckerName The *full name* of the checker. One may retrieve
321   /// this from the checker object's field \c Name, or through \c
322   /// CheckerManager::getCurrentCheckerName within the checker's registry
323   /// function.
324   /// Checker options are retrieved in the following format:
325   /// `-analyzer-config CheckerName:OptionName=Value.
326   /// @param [in] OptionName Name for option to retrieve.
327   /// @param [in] SearchInParents If set to true and the searched option was not
328   /// specified for the given checker the options for the parent packages will
329   /// be searched as well. The inner packages take precedence over the outer
330   /// ones.
331   bool getCheckerBooleanOption(StringRef CheckerName, StringRef OptionName,
332                                bool SearchInParents = false) const;
333 
334   bool getCheckerBooleanOption(const ento::CheckerBase *C, StringRef OptionName,
335                                bool SearchInParents = false) const;
336 
337   /// Interprets an option's string value as an integer value.
338   ///
339   /// If an option value is not provided, returns the given \p DefaultVal.
340   /// @param [in] CheckerName The *full name* of the checker. One may retrieve
341   /// this from the checker object's field \c Name, or through \c
342   /// CheckerManager::getCurrentCheckerName within the checker's registry
343   /// function.
344   /// Checker options are retrieved in the following format:
345   /// `-analyzer-config CheckerName:OptionName=Value.
346   /// @param [in] OptionName Name for option to retrieve.
347   /// @param [in] SearchInParents If set to true and the searched option was not
348   /// specified for the given checker the options for the parent packages will
349   /// be searched as well. The inner packages take precedence over the outer
350   /// ones.
351   int getCheckerIntegerOption(StringRef CheckerName, StringRef OptionName,
352                               bool SearchInParents = false) const;
353 
354   int getCheckerIntegerOption(const ento::CheckerBase *C, StringRef OptionName,
355                               bool SearchInParents = false) const;
356 
357   /// Query an option's string value.
358   ///
359   /// If an option value is not provided, returns the given \p DefaultVal.
360   /// @param [in] CheckerName The *full name* of the checker. One may retrieve
361   /// this from the checker object's field \c Name, or through \c
362   /// CheckerManager::getCurrentCheckerName within the checker's registry
363   /// function.
364   /// Checker options are retrieved in the following format:
365   /// `-analyzer-config CheckerName:OptionName=Value.
366   /// @param [in] OptionName Name for option to retrieve.
367   /// @param [in] SearchInParents If set to true and the searched option was not
368   /// specified for the given checker the options for the parent packages will
369   /// be searched as well. The inner packages take precedence over the outer
370   /// ones.
371   StringRef getCheckerStringOption(StringRef CheckerName, StringRef OptionName,
372                                    bool SearchInParents = false) const;
373 
374   StringRef getCheckerStringOption(const ento::CheckerBase *C,
375                                    StringRef OptionName,
376                                    bool SearchInParents = false) const;
377 
378   /// Retrieves and sets the UserMode. This is a high-level option,
379   /// which is used to set other low-level options. It is not accessible
380   /// outside of AnalyzerOptions.
381   UserModeKind getUserMode() const;
382 
383   ExplorationStrategyKind getExplorationStrategy() const;
384 
385   /// Returns the inter-procedural analysis mode.
386   IPAKind getIPAMode() const;
387 
388   /// Returns the option controlling which C++ member functions will be
389   /// considered for inlining.
390   ///
391   /// This is controlled by the 'c++-inlining' config option.
392   ///
393   /// \sa CXXMemberInliningMode
394   bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const;
395 };
396 
397 using AnalyzerOptionsRef = IntrusiveRefCntPtr<AnalyzerOptions>;
398 
399 //===----------------------------------------------------------------------===//
400 // We'll use AnalyzerOptions in the frontend, but we can't link the frontend
401 // with clangStaticAnalyzerCore, because clangStaticAnalyzerCore depends on
402 // clangFrontend.
403 //
404 // For this reason, implement some methods in this header file.
405 //===----------------------------------------------------------------------===//
406 
407 inline UserModeKind AnalyzerOptions::getUserMode() const {
408   auto K = llvm::StringSwitch<llvm::Optional<UserModeKind>>(UserMode)
409     .Case("shallow", UMK_Shallow)
410     .Case("deep", UMK_Deep)
411     .Default(None);
412   assert(K.hasValue() && "User mode is invalid.");
413   return K.getValue();
414 }
415 
416 inline std::vector<StringRef>
417 AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental) {
418   static constexpr llvm::StringLiteral StaticAnalyzerCheckerNames[] = {
419 #define GET_CHECKERS
420 #define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN)                 \
421   llvm::StringLiteral(FULLNAME),
422 #include "clang/StaticAnalyzer/Checkers/Checkers.inc"
423 #undef CHECKER
424 #undef GET_CHECKERS
425   };
426   std::vector<StringRef> Checkers;
427   for (StringRef CheckerName : StaticAnalyzerCheckerNames) {
428     if (!CheckerName.startswith("debug.") &&
429         (IncludeExperimental || !CheckerName.startswith("alpha.")))
430       Checkers.push_back(CheckerName);
431   }
432   return Checkers;
433 }
434 
435 inline std::vector<StringRef>
436 AnalyzerOptions::getRegisteredPackages(bool IncludeExperimental) {
437   static constexpr llvm::StringLiteral StaticAnalyzerPackageNames[] = {
438 #define GET_PACKAGES
439 #define PACKAGE(FULLNAME) llvm::StringLiteral(FULLNAME),
440 #include "clang/StaticAnalyzer/Checkers/Checkers.inc"
441 #undef PACKAGE
442 #undef GET_PACKAGES
443   };
444   std::vector<StringRef> Packages;
445   for (StringRef PackageName : StaticAnalyzerPackageNames) {
446     if (PackageName != "debug" &&
447         (IncludeExperimental || PackageName != "alpha"))
448       Packages.push_back(PackageName);
449   }
450   return Packages;
451 }
452 
453 } // namespace clang
454 
455 #endif // LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
456