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