clang-tools 10.0.0

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/Basic/SourceManager.h"
16 #include "clang/Tooling/Core/Diagnostic.h"
17 #include "clang/Tooling/Refactoring.h"
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/Support/Timer.h"
21
22 namespace clang {
23
24 class ASTContext;
25 class CompilerInstance;
26 namespace ast_matchers {
27 class MatchFinder;
28 }
29 namespace tooling {
30 class CompilationDatabase;
31 }
32
33 namespace tidy {
34
35 /// A detected error complete with information to display diagnostic and
36 /// automatic fix.
37 ///
38 /// This is used as an intermediate format to transport Diagnostics without a
39 /// dependency on a SourceManager.
40 ///
41 /// FIXME: Make Diagnostics flexible enough to support this directly.
42 struct ClangTidyError : tooling::Diagnostic {
43 ClangTidyError(StringRef CheckName, Level DiagLevel, StringRef BuildDirectory,
44 bool IsWarningAsError);
45
46 bool IsWarningAsError;
47 };
48
49 /// Contains displayed and ignored diagnostic counters for a ClangTidy
50 /// run.
51 struct ClangTidyStats {
52 ClangTidyStats()
53 : ErrorsDisplayed(0), ErrorsIgnoredCheckFilter(0), ErrorsIgnoredNOLINT(0),
54 ErrorsIgnoredNonUserCode(0), ErrorsIgnoredLineFilter(0) {}
55
56 unsigned ErrorsDisplayed;
57 unsigned ErrorsIgnoredCheckFilter;
58 unsigned ErrorsIgnoredNOLINT;
59 unsigned ErrorsIgnoredNonUserCode;
60 unsigned ErrorsIgnoredLineFilter;
61
62 unsigned errorsIgnored() const {
63 return ErrorsIgnoredNOLINT + ErrorsIgnoredCheckFilter +
64 ErrorsIgnoredNonUserCode + ErrorsIgnoredLineFilter;
65 }
66 };
67
68 /// Every \c ClangTidyCheck reports errors through a \c DiagnosticsEngine
69 /// provided by this context.
70 ///
71 /// A \c ClangTidyCheck always has access to the active context to report
72 /// warnings like:
73 /// \code
74 /// Context->Diag(Loc, "Single-argument constructors must be explicit")
75 /// << FixItHint::CreateInsertion(Loc, "explicit ");
76 /// \endcode
77 class ClangTidyContext {
78 public:
79 /// Initializes \c ClangTidyContext instance.
80 ClangTidyContext(std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider,
81 bool AllowEnablingAnalyzerAlphaCheckers = false);
82 /// Sets the DiagnosticsEngine that diag() will emit diagnostics to.
83 // FIXME: this is required initialization, and should be a constructor param.
84 // Fix the context -> diag engine -> consumer -> context initialization cycle.
85 void setDiagnosticsEngine(DiagnosticsEngine *DiagEngine) {
86 this->DiagEngine = DiagEngine;
87 }
88
89 ~ClangTidyContext();
90
91 /// Report any errors detected using this method.
92 ///
93 /// This is still under heavy development and will likely change towards using
94 /// tablegen'd diagnostic IDs.
95 /// FIXME: Figure out a way to manage ID spaces.
96 DiagnosticBuilder diag(StringRef CheckName, SourceLocation Loc,
97 StringRef Message,
98 DiagnosticIDs::Level Level = DiagnosticIDs::Warning);
99
100 /// Sets the \c SourceManager of the used \c DiagnosticsEngine.
101 ///
102 /// This is called from the \c ClangTidyCheck base class.
103 void setSourceManager(SourceManager *SourceMgr);
104
105 /// Should be called when starting to process new translation unit.
106 void setCurrentFile(StringRef File);
107
108 /// Returns the main file name of the current translation unit.
109 StringRef getCurrentFile() const { return CurrentFile; }
110
111 /// Sets ASTContext for the current translation unit.
112 void setASTContext(ASTContext *Context);
113
114 /// Gets the language options from the AST context.
115 const LangOptions &getLangOpts() const { return LangOpts; }
116
117 /// Returns the name of the clang-tidy check which produced this
118 /// diagnostic ID.
119 std::string getCheckName(unsigned DiagnosticID) const;
120
121 /// Returns \c true if the check is enabled for the \c CurrentFile.
122 ///
123 /// The \c CurrentFile can be changed using \c setCurrentFile.
124 bool isCheckEnabled(StringRef CheckName) const;
125
126 /// Returns \c true if the check should be upgraded to error for the
127 /// \c CurrentFile.
128 bool treatAsError(StringRef CheckName) const;
129
130 /// Returns global options.
131 const ClangTidyGlobalOptions &getGlobalOptions() const;
132
133 /// Returns options for \c CurrentFile.
134 ///
135 /// The \c CurrentFile can be changed using \c setCurrentFile.
136 const ClangTidyOptions &getOptions() const;
137
138 /// Returns options for \c File. Does not change or depend on
139 /// \c CurrentFile.
140 ClangTidyOptions getOptionsForFile(StringRef File) const;
141
142 /// Returns \c ClangTidyStats containing issued and ignored diagnostic
143 /// counters.
144 const ClangTidyStats &getStats() const { return Stats; }
145
146 /// Control profile collection in clang-tidy.
147 void setEnableProfiling(bool Profile);
148 bool getEnableProfiling() const { return Profile; }
149
150 /// Control storage of profile date.
151 void setProfileStoragePrefix(StringRef ProfilePrefix);
152 llvm::Optional<ClangTidyProfiling::StorageParams>
153 getProfileStorageParams() const;
154
155 /// Should be called when starting to process new translation unit.
156 void setCurrentBuildDirectory(StringRef BuildDirectory) {
157 CurrentBuildDirectory = BuildDirectory;
158 }
159
160 /// Returns build directory of the current translation unit.
161 const std::string &getCurrentBuildDirectory() {
162 return CurrentBuildDirectory;
163 }
164
165 /// If the experimental alpha checkers from the static analyzer can be
166 /// enabled.
167 bool canEnableAnalyzerAlphaCheckers() const {
168 return AllowEnablingAnalyzerAlphaCheckers;
169 }
170
171 using DiagLevelAndFormatString = std::pair<DiagnosticIDs::Level, std::string>;
172 DiagLevelAndFormatString getDiagLevelAndFormatString(unsigned DiagnosticID,
173 SourceLocation Loc) {
174 return DiagLevelAndFormatString(
175 static_cast<DiagnosticIDs::Level>(
176 DiagEngine->getDiagnosticLevel(DiagnosticID, Loc)),
177 DiagEngine->getDiagnosticIDs()->getDescription(DiagnosticID));
178 }
179
180 private:
181 // Writes to Stats.
182 friend class ClangTidyDiagnosticConsumer;
183
184 DiagnosticsEngine *DiagEngine;
185 std::unique_ptr<ClangTidyOptionsProvider> OptionsProvider;
186
187 std::string CurrentFile;
188 ClangTidyOptions CurrentOptions;
189 class CachedGlobList;
190 std::unique_ptr<CachedGlobList> CheckFilter;
191 std::unique_ptr<CachedGlobList> WarningAsErrorFilter;
192
193 LangOptions LangOpts;
194
195 ClangTidyStats Stats;
196
197 std::string CurrentBuildDirectory;
198
199 llvm::DenseMap<unsigned, std::string> CheckNamesByDiagnosticID;
200
201 bool Profile;
202 std::string ProfilePrefix;
203
204 bool AllowEnablingAnalyzerAlphaCheckers;
205 };
206
207 /// Check whether a given diagnostic should be suppressed due to the presence
208 /// of a "NOLINT" suppression comment.
209 /// This is exposed so that other tools that present clang-tidy diagnostics
210 /// (such as clangd) can respect the same suppression rules as clang-tidy.
211 /// This does not handle suppression of notes following a suppressed diagnostic;
212 /// that is left to the caller is it requires maintaining state in between calls
213 /// to this function.
214 /// The `CheckMacroExpansion` parameter determines whether the function should
215 /// handle the case where the diagnostic is inside a macro expansion. A degree
216 /// of control over this is needed because handling this case can require
217 /// examining source files other than the one in which the diagnostic is
218 /// located, and in some use cases we cannot rely on such other files being
219 /// mapped in the SourceMapper.
220 bool shouldSuppressDiagnostic(DiagnosticsEngine::Level DiagLevel,
221 const Diagnostic &Info, ClangTidyContext &Context,
222 bool CheckMacroExpansion = true);
223
224 /// A diagnostic consumer that turns each \c Diagnostic into a
225 /// \c SourceManager-independent \c ClangTidyError.
226 //
227 // FIXME: If we move away from unit-tests, this can be moved to a private
228 // implementation file.
229 class ClangTidyDiagnosticConsumer : public DiagnosticConsumer {
230 public:
231 ClangTidyDiagnosticConsumer(ClangTidyContext &Ctx,
232 DiagnosticsEngine *ExternalDiagEngine = nullptr,
233 bool RemoveIncompatibleErrors = true);
234
235 // FIXME: The concept of converting between FixItHints and Replacements is
236 // more generic and should be pulled out into a more useful Diagnostics
237 // library.
238 void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
239 const Diagnostic &Info) override;
240
241 // Retrieve the diagnostics that were captured.
242 std::vector<ClangTidyError> take();
243
244 private:
245 void finalizeLastError();
246 void removeIncompatibleErrors();
247
248 /// Returns the \c HeaderFilter constructed for the options set in the
249 /// context.
250 llvm::Regex *getHeaderFilter();
251
252 /// Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter
253 /// according to the diagnostic \p Location.
254 void checkFilters(SourceLocation Location, const SourceManager &Sources);
255 bool passesLineFilter(StringRef FileName, unsigned LineNumber) const;
256
257 void forwardDiagnostic(const Diagnostic &Info);
258
259 ClangTidyContext &Context;
260 DiagnosticsEngine *ExternalDiagEngine;
261 bool RemoveIncompatibleErrors;
262 std::vector<ClangTidyError> Errors;
263 std::unique_ptr<llvm::Regex> HeaderFilter;
264 bool LastErrorRelatesToUserCode;
265 bool LastErrorPassesLineFilter;
266 bool LastErrorWasIgnored;
267 };
268
269 } // end namespace tidy
270 } // end namespace clang
271
272 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYDIAGNOSTICCONSUMER_H
DiagnosticConsumer
Loc
SourceLocation Loc
&#39;#&#39; location in the include directive
Definition: IncludeOrderCheck.cpp:37
clang::tidy::ClangTidyStats::ClangTidyStats
ClangTidyStats()
Definition: ClangTidyDiagnosticConsumer.h:52
clang::tidy::ClangTidyContext::canEnableAnalyzerAlphaCheckers
bool canEnableAnalyzerAlphaCheckers() const
If the experimental alpha checkers from the static analyzer can be enabled.
Definition: ClangTidyDiagnosticConsumer.h:167
clang::tidy::ClangTidyContext::getDiagLevelAndFormatString
DiagLevelAndFormatString getDiagLevelAndFormatString(unsigned DiagnosticID, SourceLocation Loc)
Definition: ClangTidyDiagnosticConsumer.h:172
clang::tidy::ClangTidyContext::getEnableProfiling
bool getEnableProfiling() const
Definition: ClangTidyDiagnosticConsumer.h:148
clang::tidy::modernize::Message
constexpr llvm::StringLiteral Message
Definition: UseTrailingReturnTypeCheck.cpp:101
clang::tidy::ClangTidyOptions
Contains options for clang-tidy.
Definition: ClangTidyOptions.h:50
clang::tidy::ClangTidyStats::ErrorsIgnoredCheckFilter
unsigned ErrorsIgnoredCheckFilter
Definition: ClangTidyDiagnosticConsumer.h:57
clang::tidy::ClangTidyGlobalOptions
Global options.
Definition: ClangTidyOptions.h:42
clang::tidy::ClangTidyStats::ErrorsIgnoredNOLINT
unsigned ErrorsIgnoredNOLINT
Definition: ClangTidyDiagnosticConsumer.h:58
ClangTidyOptions.h
Ctx
Context Ctx
Definition: TUScheduler.cpp:237
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::ClangTidyStats::errorsIgnored
unsigned errorsIgnored() const
Definition: ClangTidyDiagnosticConsumer.h:62
clang::tidy::ClangTidyStats::ErrorsIgnoredNonUserCode
unsigned ErrorsIgnoredNonUserCode
Definition: ClangTidyDiagnosticConsumer.h:59
clang::tidy::ClangTidyContext::getLangOpts
const LangOptions & getLangOpts() const
Gets the language options from the AST context.
Definition: ClangTidyDiagnosticConsumer.h:115
clang::tidy::ClangTidyContext::getCurrentFile
StringRef getCurrentFile() const
Returns the main file name of the current translation unit.
Definition: ClangTidyDiagnosticConsumer.h:109
clang::tidy::ClangTidyDiagnosticConsumer
A diagnostic consumer that turns each Diagnostic into a SourceManager-independent ClangTidyError...
Definition: ClangTidyDiagnosticConsumer.h:229
clang::tidy::ClangTidyStats::ErrorsIgnoredLineFilter
unsigned ErrorsIgnoredLineFilter
Definition: ClangTidyDiagnosticConsumer.h:60
FileName
PathRef FileName
Definition: CodeComplete.cpp:1018
Info
FunctionInfo Info
Definition: FunctionSizeCheck.cpp:120
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::tidy::ClangTidyContext::setDiagnosticsEngine
void setDiagnosticsEngine(DiagnosticsEngine *DiagEngine)
Sets the DiagnosticsEngine that diag() will emit diagnostics to.
Definition: ClangTidyDiagnosticConsumer.h:85
clang::tidy::shouldSuppressDiagnostic
bool shouldSuppressDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info, ClangTidyContext &Context, bool CheckMacroExpansion)
Check whether a given diagnostic should be suppressed due to the presence of a "NOLINT" suppression c...
Definition: ClangTidyDiagnosticConsumer.cpp:358
HeaderFilter
static cl::opt< std::string > HeaderFilter("header-filter", cl::desc(R"( Regular expression matching the names of the headers to output diagnostics from. Diagnostics from the main file of each translation unit are always displayed. Can be used together with -line-filter. This option overrides the 'HeaderFilterRegex' option in .clang-tidy file, if any. )"), cl::init(""), cl::cat(ClangTidyCategory))
clang::tidy::ClangTidyError
A detected error complete with information to display diagnostic and automatic fix.
Definition: ClangTidyDiagnosticConsumer.h:42
clang::tidy::ClangTidyStats
Contains displayed and ignored diagnostic counters for a ClangTidy run.
Definition: ClangTidyDiagnosticConsumer.h:51
clang::tidy::ClangTidyStats::ErrorsDisplayed
unsigned ErrorsDisplayed
Definition: ClangTidyDiagnosticConsumer.h:56
clang::tidy::ClangTidyContext
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
Definition: ClangTidyDiagnosticConsumer.h:77
clang::tidy::ClangTidyContext::getStats
const ClangTidyStats & getStats() const
Returns ClangTidyStats containing issued and ignored diagnostic counters.
Definition: ClangTidyDiagnosticConsumer.h:144
clang::tidy::ClangTidyContext::setCurrentBuildDirectory
void setCurrentBuildDirectory(StringRef BuildDirectory)
Should be called when starting to process new translation unit.
Definition: ClangTidyDiagnosticConsumer.h:156
clang::tidy::ClangTidyError::IsWarningAsError
bool IsWarningAsError
Definition: ClangTidyDiagnosticConsumer.h:46
clang::tidy::ClangTidyContext::CachedGlobList
Definition: ClangTidyDiagnosticConsumer.cpp:124
clang::tidy::ClangTidyContext::getCurrentBuildDirectory
const std::string & getCurrentBuildDirectory()
Returns build directory of the current translation unit.
Definition: ClangTidyDiagnosticConsumer.h:161
clang::tidy::ClangTidyContext::DiagLevelAndFormatString
std::pair< DiagnosticIDs::Level, std::string > DiagLevelAndFormatString
Definition: ClangTidyDiagnosticConsumer.h:171
ClangTidyProfiling.h
Location
Definition: Modularize.cpp:383