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