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