clang 8.0.0

VerifyDiagnosticConsumer.h
Go to the documentation of this file.
1 //===- VerifyDiagnosticConsumer.h - Verifying Diagnostic Client -*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H
11 #define LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H
12
13 #include "clang/Basic/Diagnostic.h"
14 #include "clang/Basic/LLVM.h"
15 #include "clang/Basic/SourceLocation.h"
16 #include "clang/Lex/Preprocessor.h"
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/ADT/PointerIntPair.h"
19 #include "llvm/ADT/StringRef.h"
20 #include <cassert>
21 #include <limits>
22 #include <memory>
23 #include <string>
24 #include <vector>
25
26 namespace clang {
27
28 class FileEntry;
29 class LangOptions;
30 class SourceManager;
31 class TextDiagnosticBuffer;
32
33 /// VerifyDiagnosticConsumer - Create a diagnostic client which will use
34 /// markers in the input source to check that all the emitted diagnostics match
35 /// those expected.
36 ///
37 /// USING THE DIAGNOSTIC CHECKER:
38 ///
39 /// Indicating that a line expects an error or a warning is simple. Put a
40 /// comment on the line that has the diagnostic, use:
41 ///
42 /// \code
43 /// expected-{error,warning,remark,note}
44 /// \endcode
45 ///
46 /// to tag if it's an expected error, remark or warning, and place the expected
47 /// text between {{ and }} markers. The full text doesn't have to be included,
48 /// only enough to ensure that the correct diagnostic was emitted.
49 ///
50 /// Here's an example:
51 ///
52 /// \code
53 /// int A = B; // expected-error {{use of undeclared identifier 'B'}}
54 /// \endcode
55 ///
56 /// You can place as many diagnostics on one line as you wish. To make the code
57 /// more readable, you can use slash-newline to separate out the diagnostics.
58 ///
59 /// Alternatively, it is possible to specify the line on which the diagnostic
60 /// should appear by appending "@<line>" to "expected-<type>", for example:
61 ///
62 /// \code
63 /// #warning some text
64 /// // expected-warning@10 {{some text}}
65 /// \endcode
66 ///
67 /// The line number may be absolute (as above), or relative to the current
68 /// line by prefixing the number with either '+' or '-'.
69 ///
70 /// If the diagnostic is generated in a separate file, for example in a shared
71 /// header file, it may be beneficial to be able to declare the file in which
72 /// the diagnostic will appear, rather than placing the expected-* directive in
73 /// the actual file itself. This can be done using the following syntax:
74 ///
75 /// \code
76 /// // expected-error@path/include.h:15 {{error message}}
77 /// \endcode
78 ///
79 /// The path can be absolute or relative and the same search paths will be used
80 /// as for #include directives. The line number in an external file may be
81 /// substituted with '*' meaning that any line number will match (useful where
82 /// the included file is, for example, a system header where the actual line
83 /// number may change and is not critical).
84 ///
85 /// The simple syntax above allows each specification to match exactly one
86 /// error. You can use the extended syntax to customize this. The extended
87 /// syntax is "expected-<type> <n> {{diag text}}", where <type> is one of
88 /// "error", "warning" or "note", and <n> is a positive integer. This allows
89 /// the diagnostic to appear as many times as specified. Example:
90 ///
91 /// \code
92 /// void f(); // expected-note 2 {{previous declaration is here}}
93 /// \endcode
94 ///
95 /// Where the diagnostic is expected to occur a minimum number of times, this
96 /// can be specified by appending a '+' to the number. Example:
97 ///
98 /// \code
99 /// void f(); // expected-note 0+ {{previous declaration is here}}
100 /// void g(); // expected-note 1+ {{previous declaration is here}}
101 /// \endcode
102 ///
103 /// In the first example, the diagnostic becomes optional, i.e. it will be
104 /// swallowed if it occurs, but will not generate an error if it does not
105 /// occur. In the second example, the diagnostic must occur at least once.
106 /// As a short-hand, "one or more" can be specified simply by '+'. Example:
107 ///
108 /// \code
109 /// void g(); // expected-note + {{previous declaration is here}}
110 /// \endcode
111 ///
112 /// A range can also be specified by "<n>-<m>". Example:
113 ///
114 /// \code
115 /// void f(); // expected-note 0-1 {{previous declaration is here}}
116 /// \endcode
117 ///
118 /// In this example, the diagnostic may appear only once, if at all.
119 ///
120 /// Regex matching mode may be selected by appending '-re' to type and
121 /// including regexes wrapped in double curly braces in the directive, such as:
122 ///
123 /// \code
124 /// expected-error-re {{format specifies type 'wchar_t **' (aka '{{.+}}')}}
125 /// \endcode
126 ///
127 /// Examples matching error: "variable has incomplete type 'struct s'"
128 ///
129 /// \code
130 /// // expected-error {{variable has incomplete type 'struct s'}}
131 /// // expected-error {{variable has incomplete type}}
132 ///
133 /// // expected-error-re {{variable has type 'struct {{.}}'}}
134 /// // expected-error-re {{variable has type 'struct {{.*}}'}}
135 /// // expected-error-re {{variable has type 'struct {{(.*)}}'}}
136 /// // expected-error-re {{variable has type 'struct{{[[:space:]](.*)}}'}}
137 /// \endcode
138 ///
139 /// VerifyDiagnosticConsumer expects at least one expected-* directive to
140 /// be found inside the source code. If no diagnostics are expected the
141 /// following directive can be used to indicate this:
142 ///
143 /// \code
144 /// // expected-no-diagnostics
145 /// \endcode
146 ///
147 class VerifyDiagnosticConsumer: public DiagnosticConsumer,
148 public CommentHandler {
149 public:
150 /// Directive - Abstract class representing a parsed verify directive.
151 ///
152 class Directive {
153 public:
154 static std::unique_ptr<Directive> create(bool RegexKind,
155 SourceLocation DirectiveLoc,
156 SourceLocation DiagnosticLoc,
157 bool MatchAnyLine, StringRef Text,
158 unsigned Min, unsigned Max);
159
160 public:
161 /// Constant representing n or more matches.
162 static const unsigned MaxCount = std::numeric_limits<unsigned>::max();
163
164 SourceLocation DirectiveLoc;
165 SourceLocation DiagnosticLoc;
166 const std::string Text;
167 unsigned Min, Max;
168 bool MatchAnyLine;
169
170 Directive(const Directive &) = delete;
171 Directive &operator=(const Directive &) = delete;
172 virtual ~Directive() = default;
173
174 // Returns true if directive text is valid.
175 // Otherwise returns false and populates E.
176 virtual bool isValid(std::string &Error) = 0;
177
178 // Returns true on match.
179 virtual bool match(StringRef S) = 0;
180
181 protected:
182 Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc,
183 bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max)
184 : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc),
185 Text(Text), Min(Min), Max(Max), MatchAnyLine(MatchAnyLine) {
186 assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!");
187 assert((!DiagnosticLoc.isInvalid() || MatchAnyLine) &&
188 "DiagnosticLoc is invalid!");
189 }
190 };
191
192 using DirectiveList = std::vector<std::unique_ptr<Directive>>;
193
194 /// ExpectedData - owns directive objects and deletes on destructor.
195 struct ExpectedData {
196 DirectiveList Errors;
197 DirectiveList Warnings;
198 DirectiveList Remarks;
199 DirectiveList Notes;
200
201 void Reset() {
202 Errors.clear();
203 Warnings.clear();
204 Remarks.clear();
205 Notes.clear();
206 }
207 };
208
209 enum DirectiveStatus {
210 HasNoDirectives,
211 HasNoDirectivesReported,
212 HasExpectedNoDiagnostics,
213 HasOtherExpectedDirectives
214 };
215
216 private:
217 DiagnosticsEngine &Diags;
218 DiagnosticConsumer *PrimaryClient;
219 std::unique_ptr<DiagnosticConsumer> PrimaryClientOwner;
220 std::unique_ptr<TextDiagnosticBuffer> Buffer;
221 const Preprocessor *CurrentPreprocessor = nullptr;
222 const LangOptions *LangOpts = nullptr;
223 SourceManager *SrcManager = nullptr;
224 unsigned ActiveSourceFiles = 0;
225 DirectiveStatus Status;
226 ExpectedData ED;
227
228 void CheckDiagnostics();
229
230 void setSourceManager(SourceManager &SM) {
231 assert((!SrcManager || SrcManager == &SM) && "SourceManager changed!");
232 SrcManager = &SM;
233 }
234
235 // These facilities are used for validation in debug builds.
236 class UnparsedFileStatus {
237 llvm::PointerIntPair<const FileEntry *, 1, bool> Data;
238
239 public:
240 UnparsedFileStatus(const FileEntry *File, bool FoundDirectives)
241 : Data(File, FoundDirectives) {}
242
243 const FileEntry *getFile() const { return Data.getPointer(); }
244 bool foundDirectives() const { return Data.getInt(); }
245 };
246
247 using ParsedFilesMap = llvm::DenseMap<FileID, const FileEntry *>;
248 using UnparsedFilesMap = llvm::DenseMap<FileID, UnparsedFileStatus>;
249
250 ParsedFilesMap ParsedFiles;
251 UnparsedFilesMap UnparsedFiles;
252
253 public:
254 /// Create a new verifying diagnostic client, which will issue errors to
255 /// the currently-attached diagnostic client when a diagnostic does not match
256 /// what is expected (as indicated in the source file).
257 VerifyDiagnosticConsumer(DiagnosticsEngine &Diags);
258 ~VerifyDiagnosticConsumer() override;
259
260 void BeginSourceFile(const LangOptions &LangOpts,
261 const Preprocessor *PP) override;
262
263 void EndSourceFile() override;
264
265 enum ParsedStatus {
266 /// File has been processed via HandleComment.
267 IsParsed,
268
269 /// File has diagnostics and may have directives.
270 IsUnparsed,
271
272 /// File has diagnostics but guaranteed no directives.
273 IsUnparsedNoDirectives
274 };
275
276 /// Update lists of parsed and unparsed files.
277 void UpdateParsedFileStatus(SourceManager &SM, FileID FID, ParsedStatus PS);
278
279 bool HandleComment(Preprocessor &PP, SourceRange Comment) override;
280
281 void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
282 const Diagnostic &Info) override;
283 };
284
285 } // namespace clang
286
287 #endif // LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H
clang::VerifyDiagnosticConsumer::Directive::Min
unsigned Min
Definition: VerifyDiagnosticConsumer.h:167
clang::VerifyDiagnosticConsumer::DirectiveList
std::vector< std::unique_ptr< Directive > > DirectiveList
Definition: VerifyDiagnosticConsumer.h:192
clang::VerifyDiagnosticConsumer
VerifyDiagnosticConsumer - Create a diagnostic client which will use markers in the input source to c...
Definition: VerifyDiagnosticConsumer.h:147
clang::VerifyDiagnosticConsumer::DirectiveStatus
DirectiveStatus
Definition: VerifyDiagnosticConsumer.h:209
clang::VerifyDiagnosticConsumer::UpdateParsedFileStatus
void UpdateParsedFileStatus(SourceManager &SM, FileID FID, ParsedStatus PS)
Update lists of parsed and unparsed files.
Definition: VerifyDiagnosticConsumer.cpp:860
clang::VerifyDiagnosticConsumer::VerifyDiagnosticConsumer
VerifyDiagnosticConsumer(DiagnosticsEngine &Diags)
Create a new verifying diagnostic client, which will issue errors to the currently-attached diagnosti...
Definition: VerifyDiagnosticConsumer.cpp:54
clang::VerifyDiagnosticConsumer::IsParsed
File has been processed via HandleComment.
Definition: VerifyDiagnosticConsumer.h:267
clang::VerifyDiagnosticConsumer::Directive::DiagnosticLoc
SourceLocation DiagnosticLoc
Definition: VerifyDiagnosticConsumer.h:165
clang::VerifyDiagnosticConsumer::Directive::create
static std::unique_ptr< Directive > create(bool RegexKind, SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc, bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max)
Definition: VerifyDiagnosticConsumer.cpp:970
clang::VerifyDiagnosticConsumer::Directive::Directive
Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc, bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max)
Definition: VerifyDiagnosticConsumer.h:182
clang::DiagnosticConsumer
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
Definition: Diagnostic.h:1488
clang::VerifyDiagnosticConsumer::HasNoDirectives
Definition: VerifyDiagnosticConsumer.h:210
clang::VerifyDiagnosticConsumer::EndSourceFile
void EndSourceFile() override
Callback to inform the diagnostic client that processing of a source file has ended.
Definition: VerifyDiagnosticConsumer.cpp:120
clang::VerifyDiagnosticConsumer::ExpectedData
ExpectedData - owns directive objects and deletes on destructor.
Definition: VerifyDiagnosticConsumer.h:195
clang::VerifyDiagnosticConsumer::Directive::DirectiveLoc
SourceLocation DirectiveLoc
Definition: VerifyDiagnosticConsumer.h:164
clang::LangOptions
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:50
LLVM.h
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
clang::DiagnosticsEngine
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:149
Diagnostic.h
Defines the Diagnostic-related interfaces.
clang::VerifyDiagnosticConsumer::Directive::Directive
Directive(const Directive &)=delete
clang::VerifyDiagnosticConsumer::HandleDiagnostic
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) override
Handle this diagnostic, reporting it to the user or capturing it to a log as needed.
Definition: VerifyDiagnosticConsumer.cpp:137
clang::VerifyDiagnosticConsumer::Directive::MatchAnyLine
bool MatchAnyLine
Definition: VerifyDiagnosticConsumer.h:168
clang::VerifyDiagnosticConsumer::IsUnparsedNoDirectives
File has diagnostics but guaranteed no directives.
Definition: VerifyDiagnosticConsumer.h:273
Preprocessor.h
Defines the clang::Preprocessor interface.
clang::DiagnosticLevelMask::Error
clang::VerifyDiagnosticConsumer::HasNoDirectivesReported
Definition: VerifyDiagnosticConsumer.h:211
SM
const SourceManager & SM
Definition: Format.cpp:1490
clang::VerifyDiagnosticConsumer::HandleComment
bool HandleComment(Preprocessor &PP, SourceRange Comment) override
HandleComment - Hook into the preprocessor and extract comments containing expected errors and warnin...
Definition: VerifyDiagnosticConsumer.cpp:605
clang::VerifyDiagnosticConsumer::Directive::operator=
Directive & operator=(const Directive &)=delete
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:88
clang::VerifyDiagnosticConsumer::ExpectedData::Warnings
DirectiveList Warnings
Definition: VerifyDiagnosticConsumer.h:197
clang::FileEntry
Cached information about one file (either on disk or in the virtual file system). ...
Definition: FileManager.h:60
clang::VerifyDiagnosticConsumer::Directive::match
virtual bool match(StringRef S)=0
clang::VerifyDiagnosticConsumer::ExpectedData::Reset
void Reset()
Definition: VerifyDiagnosticConsumer.h:201
clang::VerifyDiagnosticConsumer::IsUnparsed
File has diagnostics and may have directives.
Definition: VerifyDiagnosticConsumer.h:270
clang::VerifyDiagnosticConsumer::Directive::Max
unsigned Max
Definition: VerifyDiagnosticConsumer.h:167
clang::VerifyDiagnosticConsumer::HasOtherExpectedDirectives
Definition: VerifyDiagnosticConsumer.h:213
clang::FileID
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Definition: SourceLocation.h:40
clang::VerifyDiagnosticConsumer::Directive::isValid
virtual bool isValid(std::string &Error)=0
clang::VerifyDiagnosticConsumer::ParsedStatus
ParsedStatus
Definition: VerifyDiagnosticConsumer.h:265
clang
Dataflow Directional Tag Classes.
Definition: CFGReachabilityAnalysis.h:22
clang::VerifyDiagnosticConsumer::Directive::~Directive
virtual ~Directive()=default
clang::VerifyDiagnosticConsumer::HasExpectedNoDiagnostics
Definition: VerifyDiagnosticConsumer.h:212
clang::VerifyDiagnosticConsumer::ExpectedData::Notes
DirectiveList Notes
Definition: VerifyDiagnosticConsumer.h:199
clang::VerifyDiagnosticConsumer::~VerifyDiagnosticConsumer
~VerifyDiagnosticConsumer() override
Definition: VerifyDiagnosticConsumer.cpp:62
clang::VerifyDiagnosticConsumer::Directive::Text
const std::string Text
Definition: VerifyDiagnosticConsumer.h:166
clang::VerifyDiagnosticConsumer::ExpectedData::Remarks
DirectiveList Remarks
Definition: VerifyDiagnosticConsumer.h:198
SourceLocation.h
Defines the clang::SourceLocation class and associated facilities.
clang::VerifyDiagnosticConsumer::Directive::MaxCount
static const unsigned MaxCount
Constant representing n or more matches.
Definition: VerifyDiagnosticConsumer.h:162
clang::SourceLocation::isInvalid
bool isInvalid() const
Definition: SourceLocation.h:109
clang::DiagnosticsEngine::Level
Level
The level of the diagnostic, after it has been through mapping.
Definition: Diagnostic.h:152
clang::Diagnostic
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
Definition: Diagnostic.h:1316
max
__DEVICE__ int max(int __a, int __b)
Definition: __clang_cuda_device_functions.h:1611
clang::CommentHandler
Abstract base class that describes a handler that will receive source ranges for each of the comments...
Definition: Preprocessor.h:2209
clang::SourceRange
A trivial tuple used to represent a source range.
Definition: SourceLocation.h:198
clang::VerifyDiagnosticConsumer::ExpectedData::Errors
DirectiveList Errors
Definition: VerifyDiagnosticConsumer.h:196
clang::VerifyDiagnosticConsumer::Directive
Directive - Abstract class representing a parsed verify directive.
Definition: VerifyDiagnosticConsumer.h:152
clang::SourceManager
This class handles loading and caching of source files into memory.
Definition: SourceManager.h:582
clang::VerifyDiagnosticConsumer::BeginSourceFile
void BeginSourceFile(const LangOptions &LangOpts, const Preprocessor *PP) override
Callback to inform the diagnostic client that processing of a source file is beginning.
Definition: VerifyDiagnosticConsumer.cpp:99
clang::Preprocessor
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:125