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