clang-tools  15.0.0git
ClangTidyDiagnosticConsumer.h
Go to the documentation of this file.
1 //===--- ClangTidyDiagnosticConsumer.h - clang-tidy -------------*- 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 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H
11 
12 #include "ClangTidyOptions.h"
13 #include "ClangTidyProfiling.h"
14 #include "NoLintDirectiveHandler.h"
15 #include "clang/Basic/Diagnostic.h"
16 #include "clang/Tooling/Core/Diagnostic.h"
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/ADT/StringSet.h"
19 #include "llvm/Support/Regex.h"
20 
21 namespace clang {
22 
23 class ASTContext;
24 class SourceManager;
25 
26 namespace tidy {
27 class CachedGlobList;
28 
29 /// A detected error complete with information to display diagnostic and
30 /// automatic fix.
31 ///
32 /// This is used as an intermediate format to transport Diagnostics without a
33 /// dependency on a SourceManager.
34 ///
35 /// FIXME: Make Diagnostics flexible enough to support this directly.
37  ClangTidyError(StringRef CheckName, Level DiagLevel, StringRef BuildDirectory,
38  bool IsWarningAsError);
39 
41  std::vector<std::string> EnabledDiagnosticAliases;
42 };
43 
44 /// Contains displayed and ignored diagnostic counters for a ClangTidy run.
46  unsigned ErrorsDisplayed = 0;
48  unsigned ErrorsIgnoredNOLINT = 0;
51 
52  unsigned errorsIgnored() const {
55  }
56 };
57 
58 /// Every \c ClangTidyCheck reports errors through a \c DiagnosticsEngine
59 /// provided by this context.
60 ///
61 /// A \c ClangTidyCheck always has access to the active context to report
62 /// warnings like:
63 /// \code
64 /// Context->Diag(Loc, "Single-argument constructors must be explicit")
65 /// << FixItHint::CreateInsertion(Loc, "explicit ");
66 /// \endcode
68 public:
69  /// Initializes \c ClangTidyContext instance.
70  ClangTidyContext(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
71  bool AllowEnablingAnalyzerAlphaCheckers = false);
72  /// Sets the DiagnosticsEngine that diag() will emit diagnostics to.
73  // FIXME: this is required initialization, and should be a constructor param.
74  // Fix the context -> diag engine -> consumer -> context initialization cycle.
75  void setDiagnosticsEngine(DiagnosticsEngine *DiagEngine) {
76  this->DiagEngine = DiagEngine;
77  }
78 
80 
81  /// Report any errors detected using this method.
82  ///
83  /// This is still under heavy development and will likely change towards using
84  /// tablegen'd diagnostic IDs.
85  /// FIXME: Figure out a way to manage ID spaces.
86  DiagnosticBuilder diag(StringRef CheckName, SourceLocation Loc,
87  StringRef Message,
88  DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
89 
90  DiagnosticBuilder diag(StringRef CheckName, StringRef Message,
91  DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
92 
93  DiagnosticBuilder diag(const tooling::Diagnostic &Error);
94 
95  /// Report any errors to do with reading the configuration using this method.
96  DiagnosticBuilder
97  configurationDiag(StringRef Message,
98  DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
99 
100  /// Check whether a given diagnostic should be suppressed due to the presence
101  /// of a "NOLINT" suppression comment.
102  /// This is exposed so that other tools that present clang-tidy diagnostics
103  /// (such as clangd) can respect the same suppression rules as clang-tidy.
104  /// This does not handle suppression of notes following a suppressed
105  /// diagnostic; that is left to the caller as it requires maintaining state in
106  /// between calls to this function.
107  /// If any NOLINT is malformed, e.g. a BEGIN without a subsequent END, output
108  /// \param NoLintErrors will return an error about it.
109  /// If \param AllowIO is false, the function does not attempt to read source
110  /// files from disk which are not already mapped into memory; such files are
111  /// treated as not containing a suppression comment.
112  /// \param EnableNoLintBlocks controls whether to honor NOLINTBEGIN/NOLINTEND
113  /// blocks; if false, only considers line-level disabling.
114  bool
115  shouldSuppressDiagnostic(DiagnosticsEngine::Level DiagLevel,
116  const Diagnostic &Info,
117  SmallVectorImpl<tooling::Diagnostic> &NoLintErrors,
118  bool AllowIO = true, bool EnableNoLintBlocks = true);
119 
120  /// Sets the \c SourceManager of the used \c DiagnosticsEngine.
121  ///
122  /// This is called from the \c ClangTidyCheck base class.
123  void setSourceManager(SourceManager *SourceMgr);
124 
125  /// Should be called when starting to process new translation unit.
126  void setCurrentFile(StringRef File);
127 
128  /// Returns the main file name of the current translation unit.
129  StringRef getCurrentFile() const { return CurrentFile; }
130 
131  /// Sets ASTContext for the current translation unit.
132  void setASTContext(ASTContext *Context);
133 
134  /// Gets the language options from the AST context.
135  const LangOptions &getLangOpts() const { return LangOpts; }
136 
137  /// Returns the name of the clang-tidy check which produced this
138  /// diagnostic ID.
139  std::string getCheckName(unsigned DiagnosticID) const;
140 
141  /// Returns \c true if the check is enabled for the \c CurrentFile.
142  ///
143  /// The \c CurrentFile can be changed using \c setCurrentFile.
144  bool isCheckEnabled(StringRef CheckName) const;
145 
146  /// Returns \c true if the check should be upgraded to error for the
147  /// \c CurrentFile.
148  bool treatAsError(StringRef CheckName) const;
149 
150  /// Returns global options.
152 
153  /// Returns options for \c CurrentFile.
154  ///
155  /// The \c CurrentFile can be changed using \c setCurrentFile.
156  const ClangTidyOptions &getOptions() const;
157 
158  /// Returns options for \c File. Does not change or depend on
159  /// \c CurrentFile.
160  ClangTidyOptions getOptionsForFile(StringRef File) const;
161 
162  /// Returns \c ClangTidyStats containing issued and ignored diagnostic
163  /// counters.
164  const ClangTidyStats &getStats() const { return Stats; }
165 
166  /// Control profile collection in clang-tidy.
167  void setEnableProfiling(bool Profile);
168  bool getEnableProfiling() const { return Profile; }
169 
170  /// Control storage of profile date.
171  void setProfileStoragePrefix(StringRef ProfilePrefix);
172  llvm::Optional<ClangTidyProfiling::StorageParams>
173  getProfileStorageParams() const;
174 
175  /// Should be called when starting to process new translation unit.
176  void setCurrentBuildDirectory(StringRef BuildDirectory) {
177  CurrentBuildDirectory = std::string(BuildDirectory);
178  }
179 
180  /// Returns build directory of the current translation unit.
181  const std::string &getCurrentBuildDirectory() const {
182  return CurrentBuildDirectory;
183  }
184 
185  /// If the experimental alpha checkers from the static analyzer can be
186  /// enabled.
188  return AllowEnablingAnalyzerAlphaCheckers;
189  }
190 
191  void setSelfContainedDiags(bool Value) { SelfContainedDiags = Value; }
192 
193  bool areDiagsSelfContained() const { return SelfContainedDiags; }
194 
195  using DiagLevelAndFormatString = std::pair<DiagnosticIDs::Level, std::string>;
197  SourceLocation Loc) {
199  static_cast<DiagnosticIDs::Level>(
200  DiagEngine->getDiagnosticLevel(DiagnosticID, Loc)),
201  std::string(
202  DiagEngine->getDiagnosticIDs()->getDescription(DiagnosticID)));
203  }
204 
205  void setOptionsCollector(llvm::StringSet<> *Collector) {
206  OptionsCollector = Collector;
207  }
208  llvm::StringSet<> *getOptionsCollector() const { return OptionsCollector; }
209 
210 private:
211  // Writes to Stats.
213 
214  DiagnosticsEngine *DiagEngine;
215  std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider;
216 
217  std::string CurrentFile;
218  ClangTidyOptions CurrentOptions;
219 
220  std::unique_ptr<CachedGlobList> CheckFilter;
221  std::unique_ptr<CachedGlobList> WarningAsErrorFilter;
222 
223  LangOptions LangOpts;
224 
225  ClangTidyStats Stats;
226 
227  std::string CurrentBuildDirectory;
228 
229  llvm::DenseMap<unsigned, std::string> CheckNamesByDiagnosticID;
230 
231  bool Profile;
232  std::string ProfilePrefix;
233 
235 
236  bool SelfContainedDiags;
237 
238  NoLintDirectiveHandler NoLintHandler;
239  llvm::StringSet<> *OptionsCollector = nullptr;
240 };
241 
242 /// Gets the Fix attached to \p Diagnostic.
243 /// If there isn't a Fix attached to the diagnostic and \p AnyFix is true, Check
244 /// to see if exactly one note has a Fix and return it. Otherwise return
245 /// nullptr.
246 const llvm::StringMap<tooling::Replacements> *
247 getFixIt(const tooling::Diagnostic &Diagnostic, bool AnyFix);
248 
249 /// A diagnostic consumer that turns each \c Diagnostic into a
250 /// \c SourceManager-independent \c ClangTidyError.
251 // FIXME: If we move away from unit-tests, this can be moved to a private
252 // implementation file.
254 public:
255  /// \param EnableNolintBlocks Enables diagnostic-disabling inside blocks of
256  /// code, delimited by NOLINTBEGIN and NOLINTEND.
258  DiagnosticsEngine *ExternalDiagEngine = nullptr,
259  bool RemoveIncompatibleErrors = true,
260  bool GetFixesFromNotes = false,
261  bool EnableNolintBlocks = true);
262 
263  // FIXME: The concept of converting between FixItHints and Replacements is
264  // more generic and should be pulled out into a more useful Diagnostics
265  // library.
266  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
267  const Diagnostic &Info) override;
268 
269  // Retrieve the diagnostics that were captured.
270  std::vector<ClangTidyError> take();
271 
272 private:
273  void finalizeLastError();
274  void removeIncompatibleErrors();
275  void removeDuplicatedDiagnosticsOfAliasCheckers();
276 
277  /// Returns the \c HeaderFilter constructed for the options set in the
278  /// context.
279  llvm::Regex *getHeaderFilter();
280 
281  /// Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter
282  /// according to the diagnostic \p Location.
283  void checkFilters(SourceLocation Location, const SourceManager &Sources);
284  bool passesLineFilter(StringRef FileName, unsigned LineNumber) const;
285 
286  void forwardDiagnostic(const Diagnostic &Info);
287 
288  ClangTidyContext &Context;
289  DiagnosticsEngine *ExternalDiagEngine;
290  bool RemoveIncompatibleErrors;
291  bool GetFixesFromNotes;
292  bool EnableNolintBlocks;
293  std::vector<ClangTidyError> Errors;
294  std::unique_ptr<llvm::Regex> HeaderFilter;
295  bool LastErrorRelatesToUserCode;
296  bool LastErrorPassesLineFilter;
297  bool LastErrorWasIgnored;
298 };
299 
300 } // end namespace tidy
301 } // end namespace clang
302 
303 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H
Loc
SourceLocation Loc
Definition: KernelNameRestrictionCheck.cpp:45
clang::tidy::ClangTidyContext::setCurrentBuildDirectory
void setCurrentBuildDirectory(StringRef BuildDirectory)
Should be called when starting to process new translation unit.
Definition: ClangTidyDiagnosticConsumer.h:176
clang::tidy::ClangTidyContext::setASTContext
void setASTContext(ASTContext *Context)
Sets ASTContext for the current translation unit.
Definition: ClangTidyDiagnosticConsumer.cpp:232
clang::tidy::ClangTidyDiagnosticConsumer::take
std::vector< ClangTidyError > take()
Definition: ClangTidyDiagnosticConsumer.cpp:725
clang::tidy::ClangTidyContext::getStats
const ClangTidyStats & getStats() const
Returns ClangTidyStats containing issued and ignored diagnostic counters.
Definition: ClangTidyDiagnosticConsumer.h:164
clang::tidy::ClangTidyStats::ErrorsIgnoredCheckFilter
unsigned ErrorsIgnoredCheckFilter
Definition: ClangTidyDiagnosticConsumer.h:47
clang::tidy::ClangTidyContext::getOptionsForFile
ClangTidyOptions getOptionsForFile(StringRef File) const
Returns options for File.
Definition: ClangTidyDiagnosticConsumer.cpp:245
Location
Definition: Modularize.cpp:381
DiagnosticConsumer
clang::tidy::ClangTidyContext::DiagLevelAndFormatString
std::pair< DiagnosticIDs::Level, std::string > DiagLevelAndFormatString
Definition: ClangTidyDiagnosticConsumer.h:195
clang::tidy::ClangTidyStats
Contains displayed and ignored diagnostic counters for a ClangTidy run.
Definition: ClangTidyDiagnosticConsumer.h:45
clang::tidy::ClangTidyContext::getCheckName
std::string getCheckName(unsigned DiagnosticID) const
Returns the name of the clang-tidy check which produced this diagnostic ID.
Definition: ClangTidyDiagnosticConsumer.cpp:276
clang::tidy::bugprone::Message
static const char Message[]
Definition: ReservedIdentifierCheck.cpp:31
clang::tidy::ClangTidyContext::setOptionsCollector
void setOptionsCollector(llvm::StringSet<> *Collector)
Definition: ClangTidyDiagnosticConsumer.h:205
clang::tidy::ClangTidyContext::canEnableAnalyzerAlphaCheckers
bool canEnableAnalyzerAlphaCheckers() const
If the experimental alpha checkers from the static analyzer can be enabled.
Definition: ClangTidyDiagnosticConsumer.h:187
Ctx
Context Ctx
Definition: TUScheduler.cpp:495
clang::tidy::ClangTidyDiagnosticConsumer
A diagnostic consumer that turns each Diagnostic into a SourceManager-independent ClangTidyError.
Definition: ClangTidyDiagnosticConsumer.h:253
SourceMgr
llvm::SourceMgr * SourceMgr
Definition: ConfigCompile.cpp:101
clang::tidy::ClangTidyOptions
Contains options for clang-tidy.
Definition: ClangTidyOptions.h:50
clang::tidy::ClangTidyContext::setDiagnosticsEngine
void setDiagnosticsEngine(DiagnosticsEngine *DiagEngine)
Sets the DiagnosticsEngine that diag() will emit diagnostics to.
Definition: ClangTidyDiagnosticConsumer.h:75
clang::tidy::ClangTidyContext::setSourceManager
void setSourceManager(SourceManager *SourceMgr)
Sets the SourceManager of the used DiagnosticsEngine.
Definition: ClangTidyDiagnosticConsumer.cpp:220
AllowEnablingAnalyzerAlphaCheckers
static cl::opt< bool > AllowEnablingAnalyzerAlphaCheckers("allow-enabling-analyzer-alpha-checkers", cl::init(false), cl::Hidden, cl::cat(ClangTidyCategory))
This option allows enabling the experimental alpha checkers from the static analyzer.
clang::tidy::ClangTidyError
A detected error complete with information to display diagnostic and automatic fix.
Definition: ClangTidyDiagnosticConsumer.h:36
Diagnostic
DiagnosticCallback Diagnostic
Definition: ConfigCompile.cpp:100
clang::tidy::ClangTidyStats::ErrorsIgnoredNOLINT
unsigned ErrorsIgnoredNOLINT
Definition: ClangTidyDiagnosticConsumer.h:48
clang::tidy::ClangTidyDiagnosticConsumer::HandleDiagnostic
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) override
Definition: ClangTidyDiagnosticConsumer.cpp:345
clang::tidy::ClangTidyStats::errorsIgnored
unsigned errorsIgnored() const
Definition: ClangTidyDiagnosticConsumer.h:52
clang::tidy::ClangTidyError::IsWarningAsError
bool IsWarningAsError
Definition: ClangTidyDiagnosticConsumer.h:40
clang::tidy::ClangTidyContext::setCurrentFile
void setCurrentFile(StringRef File)
Should be called when starting to process new translation unit.
Definition: ClangTidyDiagnosticConsumer.cpp:224
clang::tidy::ClangTidyContext
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
Definition: ClangTidyDiagnosticConsumer.h:67
clang::tidy::ClangTidyContext::getGlobalOptions
const ClangTidyGlobalOptions & getGlobalOptions() const
Returns global options.
Definition: ClangTidyDiagnosticConsumer.cpp:237
clang::tidy::ClangTidyContext::getLangOpts
const LangOptions & getLangOpts() const
Gets the language options from the AST context.
Definition: ClangTidyDiagnosticConsumer.h:135
clang::tidy::ClangTidyContext::setEnableProfiling
void setEnableProfiling(bool Profile)
Control profile collection in clang-tidy.
Definition: ClangTidyDiagnosticConsumer.cpp:252
FileName
StringRef FileName
Definition: KernelNameRestrictionCheck.cpp:46
clang::tidy::ClangTidyStats::ErrorsIgnoredLineFilter
unsigned ErrorsIgnoredLineFilter
Definition: ClangTidyDiagnosticConsumer.h:50
clang::tidy::ClangTidyStats::ErrorsIgnoredNonUserCode
unsigned ErrorsIgnoredNonUserCode
Definition: ClangTidyDiagnosticConsumer.h:49
clang::tidy::ClangTidyGlobalOptions
Global options.
Definition: ClangTidyOptions.h:42
clang::tidy::ClangTidyContext::getOptions
const ClangTidyOptions & getOptions() const
Returns options for CurrentFile.
Definition: ClangTidyDiagnosticConsumer.cpp:241
clang::tidy::ClangTidyStats::ErrorsDisplayed
unsigned ErrorsDisplayed
Definition: ClangTidyDiagnosticConsumer.h:46
Collector
std::shared_ptr< SymbolCollector > Collector
Definition: SymbolCollectorTests.cpp:258
clang::tidy::ClangTidyContext::setSelfContainedDiags
void setSelfContainedDiags(bool Value)
Definition: ClangTidyDiagnosticConsumer.h:191
clang::tidy::ClangTidyContext::~ClangTidyContext
~ClangTidyContext()
clang::tidy::ClangTidyContext::isCheckEnabled
bool isCheckEnabled(StringRef CheckName) const
Returns true if the check is enabled for the CurrentFile.
Definition: ClangTidyDiagnosticConsumer.cpp:266
clang::tidy::ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer
ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx, DiagnosticsEngine *ExternalDiagEngine=nullptr, bool RemoveIncompatibleErrors=true, bool GetFixesFromNotes=false, bool EnableNolintBlocks=true)
Definition: ClangTidyDiagnosticConsumer.cpp:288
clang::tidy::ClangTidyContext::getDiagLevelAndFormatString
DiagLevelAndFormatString getDiagLevelAndFormatString(unsigned DiagnosticID, SourceLocation Loc)
Definition: ClangTidyDiagnosticConsumer.h:196
Info
FunctionInfo Info
Definition: FunctionSizeCheck.cpp:121
clang::tidy::NoLintDirectiveHandler
This class is used to locate NOLINT comments in the file being analyzed, to decide whether a diagnost...
Definition: NoLintDirectiveHandler.h:33
clang::tidy::ClangTidyContext::ClangTidyContext
ClangTidyContext(std::unique_ptr< ClangTidyOptionsProvider > OptionsProvider, bool AllowEnablingAnalyzerAlphaCheckers=false)
Initializes ClangTidyContext instance.
Definition: ClangTidyDiagnosticConsumer.cpp:160
clang::tidy::ClangTidyContext::shouldSuppressDiagnostic
bool shouldSuppressDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info, SmallVectorImpl< tooling::Diagnostic > &NoLintErrors, bool AllowIO=true, bool EnableNoLintBlocks=true)
Check whether a given diagnostic should be suppressed due to the presence of a "NOLINT" suppression c...
Definition: ClangTidyDiagnosticConsumer.cpp:211
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::tidy::ClangTidyContext::getCurrentBuildDirectory
const std::string & getCurrentBuildDirectory() const
Returns build directory of the current translation unit.
Definition: ClangTidyDiagnosticConsumer.h:181
LangOpts
const LangOptions * LangOpts
Definition: ExtractFunction.cpp:366
ClangTidyProfiling.h
clang::tidy::ClangTidyContext::getEnableProfiling
bool getEnableProfiling() const
Definition: ClangTidyDiagnosticConsumer.h:168
clang::tidy::ClangTidyContext::getOptionsCollector
llvm::StringSet * getOptionsCollector() const
Definition: ClangTidyDiagnosticConsumer.h:208
clang::tidy::getFixIt
const llvm::StringMap< tooling::Replacements > * getFixIt(const tooling::Diagnostic &Diagnostic, bool GetFixFromNotes)
Gets the Fix attached to Diagnostic.
Definition: ClangTidyDiagnosticConsumer.cpp:325
clang::tidy::ClangTidyContext::diag
DiagnosticBuilder diag(StringRef CheckName, SourceLocation Loc, StringRef Message, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Report any errors detected using this method.
Definition: ClangTidyDiagnosticConsumer.cpp:174
ClangTidyOptions.h
clang::tidy::ClangTidyContext::getCurrentFile
StringRef getCurrentFile() const
Returns the main file name of the current translation unit.
Definition: ClangTidyDiagnosticConsumer.h:129
Warning
constexpr static llvm::SourceMgr::DiagKind Warning
Definition: ConfigCompile.cpp:592
clang::tidy::ClangTidyContext::getProfileStorageParams
llvm::Optional< ClangTidyProfiling::StorageParams > getProfileStorageParams() const
Definition: ClangTidyDiagnosticConsumer.cpp:259
clang::tidy::ClangTidyError::ClangTidyError
ClangTidyError(StringRef CheckName, Level DiagLevel, StringRef BuildDirectory, bool IsWarningAsError)
Definition: ClangTidyDiagnosticConsumer.cpp:154
clang::tidy::ClangTidyContext::treatAsError
bool treatAsError(StringRef CheckName) const
Returns true if the check should be upgraded to error for the CurrentFile.
Definition: ClangTidyDiagnosticConsumer.cpp:271
clang::tidy::ClangTidyContext::areDiagsSelfContained
bool areDiagsSelfContained() const
Definition: ClangTidyDiagnosticConsumer.h:193
clang::tidy::ClangTidyError::EnabledDiagnosticAliases
std::vector< std::string > EnabledDiagnosticAliases
Definition: ClangTidyDiagnosticConsumer.h:41
clang::tidy::ClangTidyContext::configurationDiag
DiagnosticBuilder configurationDiag(StringRef Message, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Report any errors to do with reading the configuration using this method.
Definition: ClangTidyDiagnosticConsumer.cpp:205
clang::tidy::ClangTidyContext::setProfileStoragePrefix
void setProfileStoragePrefix(StringRef ProfilePrefix)
Control storage of profile date.
Definition: ClangTidyDiagnosticConsumer.cpp:254
NoLintDirectiveHandler.h