 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
67.6% |
23 / 34 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
79.4% |
27 / 34 |
| |
|
Line Coverage: |
99.5% |
181 / 182 |
| |
 |
|
 |
 |
|
 |
|
| Programs: |
163 |
|
Runs |
269563 |
| |
 |
|
 |
1 : //===--- Diagnostic.h - C Language Family Diagnostic Handling ---*- 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 : // This file defines the Diagnostic-related interfaces.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #ifndef LLVM_CLANG_DIAGNOSTIC_H
15 : #define LLVM_CLANG_DIAGNOSTIC_H
16 :
17 : #include "clang/Basic/SourceLocation.h"
18 : #include "llvm/ADT/StringRef.h"
19 : #include "llvm/Support/type_traits.h"
20 : #include <string>
21 : #include <vector>
22 : #include <cassert>
23 :
24 : namespace llvm {
25 : template <typename T> class SmallVectorImpl;
26 : class raw_ostream;
27 : }
28 :
29 : namespace clang {
30 : class DeclContext;
31 : class DiagnosticBuilder;
32 : class DiagnosticClient;
33 : class FileManager;
34 : class IdentifierInfo;
35 : class LangOptions;
36 : class PartialDiagnostic;
37 : class Preprocessor;
38 : class SourceManager;
39 : class SourceRange;
40 :
41 : // Import the diagnostic enums themselves.
42 : namespace diag {
43 : // Start position for diagnostics.
44 : enum {
45 : DIAG_START_DRIVER = 300,
46 : DIAG_START_FRONTEND = DIAG_START_DRIVER + 100,
47 : DIAG_START_LEX = DIAG_START_FRONTEND + 100,
48 : DIAG_START_PARSE = DIAG_START_LEX + 300,
49 : DIAG_START_AST = DIAG_START_PARSE + 300,
50 : DIAG_START_SEMA = DIAG_START_AST + 100,
51 : DIAG_START_ANALYSIS = DIAG_START_SEMA + 1500,
52 : DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
53 : };
54 :
55 : class CustomDiagInfo;
56 :
57 : /// diag::kind - All of the diagnostics that can be emitted by the frontend.
58 : typedef unsigned kind;
59 :
60 : // Get typedefs for common diagnostics.
61 : enum {
62 : #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
63 : #include "clang/Basic/DiagnosticCommonKinds.inc"
64 : NUM_BUILTIN_COMMON_DIAGNOSTICS
65 : #undef DIAG
66 : };
67 :
68 : /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
69 : /// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR
70 : /// (emit as an error). It allows clients to map errors to
71 : /// MAP_ERROR/MAP_DEFAULT or MAP_FATAL (stop emitting diagnostics after this
72 : /// one).
73 : enum Mapping {
74 : // NOTE: 0 means "uncomputed".
75 : MAP_IGNORE = 1, //< Map this diagnostic to nothing, ignore it.
76 : MAP_WARNING = 2, //< Map this diagnostic to a warning.
77 : MAP_ERROR = 3, //< Map this diagnostic to an error.
78 : MAP_FATAL = 4, //< Map this diagnostic to a fatal error.
79 :
80 : /// Map this diagnostic to "warning", but make it immune to -Werror. This
81 : /// happens when you specify -Wno-error=foo.
82 : MAP_WARNING_NO_WERROR = 5,
83 : /// Map this diagnostic to "error", but make it immune to -Wfatal-errors.
84 : /// This happens for -Wno-fatal-errors=foo.
85 : MAP_ERROR_NO_WFATAL = 6
86 : };
87 : }
88 :
89 : /// \brief Annotates a diagnostic with some code that should be
90 : /// inserted, removed, or replaced to fix the problem.
91 : ///
92 : /// This kind of hint should be used when we are certain that the
93 : /// introduction, removal, or modification of a particular (small!)
94 : /// amount of code will correct a compilation error. The compiler
95 : /// should also provide full recovery from such errors, such that
96 : /// suppressing the diagnostic output can still result in successful
97 : /// compilation.
98 258521: class CodeModificationHint {
99 : public:
100 : /// \brief Tokens that should be removed to correct the error.
101 : SourceRange RemoveRange;
102 :
103 : /// \brief The location at which we should insert code to correct
104 : /// the error.
105 : SourceLocation InsertionLoc;
106 :
107 : /// \brief The actual code to insert at the insertion location, as a
108 : /// string.
109 : std::string CodeToInsert;
110 :
111 : /// \brief Empty code modification hint, indicating that no code
112 : /// modification is known.
113 257216: CodeModificationHint() : RemoveRange(), InsertionLoc() { }
114 :
115 898: bool isNull() const {
594: branch 1 taken
304: branch 2 taken
298: branch 4 taken
296: branch 5 taken
116 898: return !RemoveRange.isValid() && !InsertionLoc.isValid();
117 : }
118 :
119 : /// \brief Create a code modification hint that inserts the given
120 : /// code string at a specific location.
121 : static CodeModificationHint CreateInsertion(SourceLocation InsertionLoc,
122 287: llvm::StringRef Code) {
123 287: CodeModificationHint Hint;
124 287: Hint.InsertionLoc = InsertionLoc;
125 287: Hint.CodeToInsert = Code;
126 : return Hint;
127 : }
128 :
129 : /// \brief Create a code modification hint that removes the given
130 : /// source range.
131 177: static CodeModificationHint CreateRemoval(SourceRange RemoveRange) {
132 177: CodeModificationHint Hint;
133 177: Hint.RemoveRange = RemoveRange;
134 : return Hint;
135 : }
136 :
137 : /// \brief Create a code modification hint that replaces the given
138 : /// source range with the given code string.
139 : static CodeModificationHint CreateReplacement(SourceRange RemoveRange,
140 121: llvm::StringRef Code) {
141 121: CodeModificationHint Hint;
142 121: Hint.RemoveRange = RemoveRange;
143 121: Hint.InsertionLoc = RemoveRange.getBegin();
144 121: Hint.CodeToInsert = Code;
145 : return Hint;
146 : }
147 : };
148 :
149 : /// Diagnostic - This concrete class is used by the front-end to report
150 : /// problems and issues. It massages the diagnostics (e.g. handling things like
151 : /// "report warnings as errors" and passes them off to the DiagnosticClient for
152 : /// reporting to the user.
153 : class Diagnostic {
154 : public:
155 : /// Level - The level of the diagnostic, after it has been through mapping.
156 : enum Level {
157 : Ignored, Note, Warning, Error, Fatal
158 : };
159 :
160 : /// ExtensionHandling - How do we handle otherwise-unmapped extension? This
161 : /// is controlled by -pedantic and -pedantic-errors.
162 : enum ExtensionHandling {
163 : Ext_Ignore, Ext_Warn, Ext_Error
164 : };
165 :
166 : enum ArgumentKind {
167 : ak_std_string, // std::string
168 : ak_c_string, // const char *
169 : ak_sint, // int
170 : ak_uint, // unsigned
171 : ak_identifierinfo, // IdentifierInfo
172 : ak_qualtype, // QualType
173 : ak_declarationname, // DeclarationName
174 : ak_nameddecl, // NamedDecl *
175 : ak_nestednamespec, // NestedNameSpecifier *
176 : ak_declcontext // DeclContext *
177 : };
178 :
179 : /// ArgumentValue - This typedef represents on argument value, which is a
180 : /// union discriminated by ArgumentKind, with a value.
181 : typedef std::pair<ArgumentKind, intptr_t> ArgumentValue;
182 :
183 : private:
184 : unsigned char AllExtensionsSilenced; // Used by __extension__
185 : bool IgnoreAllWarnings; // Ignore all warnings: -w
186 : bool WarningsAsErrors; // Treat warnings like errors:
187 : bool ErrorsAsFatal; // Treat errors like fatal errors.
188 : bool SuppressSystemWarnings; // Suppress warnings in system headers.
189 : bool SuppressAllDiagnostics; // Suppress all diagnostics.
190 : ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
191 : DiagnosticClient *Client;
192 :
193 : /// DiagMappings - Mapping information for diagnostics. Mapping info is
194 : /// packed into four bits per diagnostic. The low three bits are the mapping
195 : /// (an instance of diag::Mapping), or zero if unset. The high bit is set
196 : /// when the mapping was established as a user mapping. If the high bit is
197 : /// clear, then the low bits are set to the default value, and should be
198 : /// mapped with -pedantic, -Werror, etc.
199 :
200 : typedef std::vector<unsigned char> DiagMappings;
201 : mutable std::vector<DiagMappings> DiagMappingsStack;
202 :
203 : /// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or
204 : /// fatal error is emitted, and is sticky.
205 : bool ErrorOccurred;
206 : bool FatalErrorOccurred;
207 :
208 : /// LastDiagLevel - This is the level of the last diagnostic emitted. This is
209 : /// used to emit continuation diagnostics with the same level as the
210 : /// diagnostic that they follow.
211 : Diagnostic::Level LastDiagLevel;
212 :
213 : unsigned NumDiagnostics; // Number of diagnostics reported
214 : unsigned NumErrors; // Number of diagnostics that are errors
215 :
216 : /// CustomDiagInfo - Information for uniquing and looking up custom diags.
217 : diag::CustomDiagInfo *CustomDiagInfo;
218 :
219 : /// ArgToStringFn - A function pointer that converts an opaque diagnostic
220 : /// argument to a strings. This takes the modifiers and argument that was
221 : /// present in the diagnostic.
222 : ///
223 : /// The PrevArgs array (whose length is NumPrevArgs) indicates the previous
224 : /// arguments formatted for this diagnostic. Implementations of this function
225 : /// can use this information to avoid redundancy across arguments.
226 : ///
227 : /// This is a hack to avoid a layering violation between libbasic and libsema.
228 : typedef void (*ArgToStringFnTy)(ArgumentKind Kind, intptr_t Val,
229 : const char *Modifier, unsigned ModifierLen,
230 : const char *Argument, unsigned ArgumentLen,
231 : const ArgumentValue *PrevArgs,
232 : unsigned NumPrevArgs,
233 : llvm::SmallVectorImpl<char> &Output,
234 : void *Cookie);
235 : void *ArgToStringCookie;
236 : ArgToStringFnTy ArgToStringFn;
237 : public:
238 : explicit Diagnostic(DiagnosticClient *client = 0);
239 : ~Diagnostic();
240 :
241 : //===--------------------------------------------------------------------===//
242 : // Diagnostic characterization methods, used by a client to customize how
243 : //
244 :
245 6558: DiagnosticClient *getClient() { return Client; }
246 : const DiagnosticClient *getClient() const { return Client; }
247 :
248 : /// pushMappings - Copies the current DiagMappings and pushes the new copy
249 : /// onto the top of the stack.
250 : void pushMappings();
251 :
252 : /// popMappings - Pops the current DiagMappings off the top of the stack
253 : /// causing the new top of the stack to be the active mappings. Returns
254 : /// true if the pop happens, false if there is only one DiagMapping on the
255 : /// stack.
256 : bool popMappings();
257 :
258 10676: void setClient(DiagnosticClient* client) { Client = client; }
259 :
260 : /// setIgnoreAllWarnings - When set to true, any unmapped warnings are
261 : /// ignored. If this and WarningsAsErrors are both set, then this one wins.
262 2583: void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; }
263 : bool getIgnoreAllWarnings() const { return IgnoreAllWarnings; }
264 :
265 : /// setWarningsAsErrors - When set to true, any warnings reported are issued
266 : /// as errors.
267 210: void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; }
268 : bool getWarningsAsErrors() const { return WarningsAsErrors; }
269 :
270 : /// setErrorsAsFatal - When set to true, any error reported is made a
271 : /// fatal error.
272 0: void setErrorsAsFatal(bool Val) { ErrorsAsFatal = Val; }
273 : bool getErrorsAsFatal() const { return ErrorsAsFatal; }
274 :
275 : /// setSuppressSystemWarnings - When set to true mask warnings that
276 : /// come from system headers.
277 2583: void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; }
278 595: bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; }
279 :
280 : /// \brief Suppress all diagnostics, to silence the front end when we
281 : /// know that we don't want any more diagnostics to be passed along to the
282 : /// client
283 87: void setSuppressAllDiagnostics(bool Val = true) {
284 87: SuppressAllDiagnostics = Val;
285 87: }
286 : bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; }
287 :
288 : /// \brief Pretend that the last diagnostic issued was ignored. This can
289 : /// be used by clients who suppress diagnostics themselves.
290 24: void setLastDiagnosticIgnored() {
291 24: LastDiagLevel = Ignored;
292 24: }
293 :
294 : /// setExtensionHandlingBehavior - This controls whether otherwise-unmapped
295 : /// extension diagnostics are mapped onto ignore/warning/error. This
296 : /// corresponds to the GCC -pedantic and -pedantic-errors option.
297 2583: void setExtensionHandlingBehavior(ExtensionHandling H) {
298 2583: ExtBehavior = H;
299 2583: }
300 :
301 : /// AllExtensionsSilenced - This is a counter bumped when an __extension__
302 : /// block is encountered. When non-zero, all extension diagnostics are
303 : /// entirely silenced, no matter how they are mapped.
304 549: void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; }
305 549: void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; }
306 82058: bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; }
307 :
308 : /// setDiagnosticMapping - This allows the client to specify that certain
309 : /// warnings are ignored. Notes can never be mapped, errors can only be
310 : /// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily.
311 698: void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map) {
312 : assert(Diag < diag::DIAG_UPPER_LIMIT &&
0: branch 0 not taken
698: branch 1 taken
313 698: "Can only map builtin diagnostics");
314 : assert((isBuiltinWarningOrExtension(Diag) || Map == diag::MAP_FATAL) &&
0: branch 1 not taken
698: branch 2 taken
698: branch 3 taken
698: branch 4 taken
315 698: "Cannot map errors!");
316 698: setDiagnosticMappingInternal(Diag, Map, true);
317 698: }
318 :
319 : /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
320 : /// "unknown-pragmas" to have the specified mapping. This returns true and
321 : /// ignores the request if "Group" was unknown, false otherwise.
322 : bool setDiagnosticGroupMapping(const char *Group, diag::Mapping Map);
323 :
324 39275: bool hasErrorOccurred() const { return ErrorOccurred; }
325 206: bool hasFatalErrorOccurred() const { return FatalErrorOccurred; }
326 :
327 6662: unsigned getNumErrors() const { return NumErrors; }
328 2511: unsigned getNumDiagnostics() const { return NumDiagnostics; }
329 :
330 : /// getCustomDiagID - Return an ID for a diagnostic with the specified message
331 : /// and level. If this is the first request for this diagnosic, it is
332 : /// registered and created, otherwise the existing ID is returned.
333 : unsigned getCustomDiagID(Level L, llvm::StringRef Message);
334 :
335 :
336 : /// ConvertArgToString - This method converts a diagnostic argument (as an
337 : /// intptr_t) into the string that represents it.
338 : void ConvertArgToString(ArgumentKind Kind, intptr_t Val,
339 : const char *Modifier, unsigned ModLen,
340 : const char *Argument, unsigned ArgLen,
341 : const ArgumentValue *PrevArgs, unsigned NumPrevArgs,
342 4577: llvm::SmallVectorImpl<char> &Output) const {
343 : ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen,
344 4577: PrevArgs, NumPrevArgs, Output, ArgToStringCookie);
345 4577: }
346 :
347 2239: void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) {
348 2239: ArgToStringFn = Fn;
349 2239: ArgToStringCookie = Cookie;
350 2239: }
351 :
352 : //===--------------------------------------------------------------------===//
353 : // Diagnostic classification and reporting interfaces.
354 : //
355 :
356 : /// getDescription - Given a diagnostic ID, return a description of the
357 : /// issue.
358 : const char *getDescription(unsigned DiagID) const;
359 :
360 : /// isNoteWarningOrExtension - Return true if the unmapped diagnostic
361 : /// level of the specified diagnostic ID is a Warning or Extension.
362 : /// This only works on builtin diagnostics, not custom ones, and is not legal to
363 : /// call on NOTEs.
364 : static bool isBuiltinWarningOrExtension(unsigned DiagID);
365 :
366 : /// \brief Determine whether the given built-in diagnostic ID is a
367 : /// Note.
368 : static bool isBuiltinNote(unsigned DiagID);
369 :
370 : /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
371 : /// ID is for an extension of some sort.
372 : ///
373 : static bool isBuiltinExtensionDiag(unsigned DiagID);
374 :
375 : /// getWarningOptionForDiag - Return the lowest-level warning option that
376 : /// enables the specified diagnostic. If there is no -Wfoo flag that controls
377 : /// the diagnostic, this returns null.
378 : static const char *getWarningOptionForDiag(unsigned DiagID);
379 :
380 : /// \brief Determines whether the given built-in diagnostic ID is
381 : /// for an error that is suppressed if it occurs during C++ template
382 : /// argument deduction.
383 : ///
384 : /// When an error is suppressed due to SFINAE, the template argument
385 : /// deduction fails but no diagnostic is emitted. Certain classes of
386 : /// errors, such as those errors that involve C++ access control,
387 : /// are not SFINAE errors.
388 : static bool isBuiltinSFINAEDiag(unsigned DiagID);
389 :
390 : /// getDiagnosticLevel - Based on the way the client configured the Diagnostic
391 : /// object, classify the specified diagnostic ID into a Level, consumable by
392 : /// the DiagnosticClient.
393 : Level getDiagnosticLevel(unsigned DiagID) const;
394 :
395 : /// Report - Issue the message to the client. @c DiagID is a member of the
396 : /// @c diag::kind enum. This actually returns aninstance of DiagnosticBuilder
397 : /// which emits the diagnostics (through @c ProcessDiag) when it is destroyed.
398 : /// @c Pos represents the source location associated with the diagnostic,
399 : /// which can be an invalid location if no position information is available.
400 : inline DiagnosticBuilder Report(FullSourceLoc Pos, unsigned DiagID);
401 : inline DiagnosticBuilder Report(unsigned DiagID);
402 :
403 : /// \brief Clear out the current diagnostic.
404 18948: void Clear() { CurDiagID = ~0U; }
405 :
406 : /// Deserialize - Deserialize the first diagnostic within the memory
407 : /// [Memory, MemoryEnd), producing a new diagnostic builder describing the
408 : /// deserialized diagnostic. If the memory does not contain a
409 : /// diagnostic, returns a diagnostic builder with no diagnostic ID.
410 : DiagnosticBuilder Deserialize(FileManager &FM, SourceManager &SM,
411 : const char *&Memory, const char *MemoryEnd);
412 :
413 : private:
414 : /// getDiagnosticMappingInfo - Return the mapping info currently set for the
415 : /// specified builtin diagnostic. This returns the high bit encoding, or zero
416 : /// if the field is completely uninitialized.
417 41421: unsigned getDiagnosticMappingInfo(diag::kind Diag) const {
418 41421: const DiagMappings ¤tMappings = DiagMappingsStack.back();
419 41421: return (diag::Mapping)((currentMappings[Diag/2] >> (Diag & 1)*4) & 15);
420 : }
421 :
422 : void setDiagnosticMappingInternal(unsigned DiagId, unsigned Map,
423 13663: bool isUser) const {
698: branch 0 taken
12965: branch 1 taken
424 13663: if (isUser) Map |= 8; // Set the high bit for user mappings.
425 13663: unsigned char &Slot = DiagMappingsStack.back()[DiagId/2];
426 13663: unsigned Shift = (DiagId & 1)*4;
427 13663: Slot &= ~(15 << Shift);
428 13663: Slot |= Map << Shift;
429 13663: }
430 :
431 : /// getDiagnosticLevel - This is an internal implementation helper used when
432 : /// DiagClass is already known.
433 : Level getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const;
434 :
435 : // This is private state used by DiagnosticBuilder. We put it here instead of
436 : // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight
437 : // object. This implementation choice means that we can only have one
438 : // diagnostic "in flight" at a time, but this seems to be a reasonable
439 : // tradeoff to keep these objects small. Assertions verify that only one
440 : // diagnostic is in flight at a time.
441 : friend class DiagnosticBuilder;
442 : friend class DiagnosticInfo;
443 :
444 : /// CurDiagLoc - This is the location of the current diagnostic that is in
445 : /// flight.
446 : FullSourceLoc CurDiagLoc;
447 :
448 : /// CurDiagID - This is the ID of the current diagnostic that is in flight.
449 : /// This is set to ~0U when there is no diagnostic in flight.
450 : unsigned CurDiagID;
451 :
452 : enum {
453 : /// MaxArguments - The maximum number of arguments we can hold. We currently
454 : /// only support up to 10 arguments (%0-%9). A single diagnostic with more
455 : /// than that almost certainly has to be simplified anyway.
456 : MaxArguments = 10
457 : };
458 :
459 : /// NumDiagArgs - This contains the number of entries in Arguments.
460 : signed char NumDiagArgs;
461 : /// NumRanges - This is the number of ranges in the DiagRanges array.
462 : unsigned char NumDiagRanges;
463 : /// \brief The number of code modifications hints in the
464 : /// CodeModificationHints array.
465 : unsigned char NumCodeModificationHints;
466 :
467 : /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum
468 : /// values, with one for each argument. This specifies whether the argument
469 : /// is in DiagArgumentsStr or in DiagArguments.
470 : unsigned char DiagArgumentsKind[MaxArguments];
471 :
472 : /// DiagArgumentsStr - This holds the values of each string argument for the
473 : /// current diagnostic. This value is only used when the corresponding
474 : /// ArgumentKind is ak_std_string.
475 : std::string DiagArgumentsStr[MaxArguments];
476 :
477 : /// DiagArgumentsVal - The values for the various substitution positions. This
478 : /// is used when the argument is not an std::string. The specific value is
479 : /// mangled into an intptr_t and the intepretation depends on exactly what
480 : /// sort of argument kind it is.
481 : intptr_t DiagArgumentsVal[MaxArguments];
482 :
483 : /// DiagRanges - The list of ranges added to this diagnostic. It currently
484 : /// only support 10 ranges, could easily be extended if needed.
485 : SourceRange DiagRanges[10];
486 :
487 : enum { MaxCodeModificationHints = 3 };
488 :
489 : /// CodeModificationHints - If valid, provides a hint with some code
490 : /// to insert, remove, or modify at a particular position.
491 : CodeModificationHint CodeModificationHints[MaxCodeModificationHints];
492 :
493 : /// ProcessDiag - This is the method used to report a diagnostic that is
494 : /// finally fully formed.
495 : ///
496 : /// \returns true if the diagnostic was emitted, false if it was
497 : /// suppressed.
498 : bool ProcessDiag();
499 : };
500 :
501 : //===----------------------------------------------------------------------===//
502 : // DiagnosticBuilder
503 : //===----------------------------------------------------------------------===//
504 :
505 : /// DiagnosticBuilder - This is a little helper class used to produce
506 : /// diagnostics. This is constructed by the Diagnostic::Report method, and
507 : /// allows insertion of extra information (arguments and source ranges) into the
508 : /// currently "in flight" diagnostic. When the temporary for the builder is
509 : /// destroyed, the diagnostic is issued.
510 : ///
511 : /// Note that many of these will be created as temporary objects (many call
512 : /// sites), so we want them to be small and we never want their address taken.
513 : /// This ensures that compilers with somewhat reasonable optimizers will promote
514 : /// the common fields to registers, eliminating increments of the NumArgs field,
515 : /// for example.
516 : class DiagnosticBuilder {
517 : mutable Diagnostic *DiagObj;
518 : mutable unsigned NumArgs, NumRanges, NumCodeModificationHints;
519 :
520 : void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT
521 : friend class Diagnostic;
522 18903: explicit DiagnosticBuilder(Diagnostic *diagObj)
523 : : DiagObj(diagObj), NumArgs(0), NumRanges(0),
524 18903: NumCodeModificationHints(0) {}
525 :
526 : public:
527 : /// Copy constructor. When copied, this "takes" the diagnostic info from the
528 : /// input and neuters it.
529 15710: DiagnosticBuilder(const DiagnosticBuilder &D) {
530 15710: DiagObj = D.DiagObj;
531 15710: D.DiagObj = 0;
532 15710: NumArgs = D.NumArgs;
533 15710: NumRanges = D.NumRanges;
534 15710: NumCodeModificationHints = D.NumCodeModificationHints;
535 15710: }
536 :
537 : /// \brief Simple enumeration value used to give a name to the
538 : /// suppress-diagnostic constructor.
539 : enum SuppressKind { Suppress };
540 :
541 : /// \brief Create an empty DiagnosticBuilder object that represents
542 : /// no actual diagnostic.
543 24: explicit DiagnosticBuilder(SuppressKind)
544 24: : DiagObj(0), NumArgs(0), NumRanges(0), NumCodeModificationHints(0) { }
545 :
546 : /// \brief Force the diagnostic builder to emit the diagnostic now.
547 : ///
548 : /// Once this function has been called, the DiagnosticBuilder object
549 : /// should not be used again before it is destroyed.
550 : ///
551 : /// \returns true if a diagnostic was emitted, false if the
552 : /// diagnostic was suppressed.
553 50317: bool Emit() {
554 : // If DiagObj is null, then its soul was stolen by the copy ctor
555 : // or the user called Emit().
31433: branch 0 taken
18884: branch 1 taken
556 50317: if (DiagObj == 0) return false;
557 :
558 : // When emitting diagnostics, we set the final argument count into
559 : // the Diagnostic object.
560 18884: DiagObj->NumDiagArgs = NumArgs;
561 18884: DiagObj->NumDiagRanges = NumRanges;
562 18884: DiagObj->NumCodeModificationHints = NumCodeModificationHints;
563 :
564 : // Process the diagnostic, sending the accumulated information to the
565 : // DiagnosticClient.
566 18884: bool Emitted = DiagObj->ProcessDiag();
567 :
568 : // Clear out the current diagnostic object.
569 18884: DiagObj->Clear();
570 :
571 : // This diagnostic is dead.
572 18884: DiagObj = 0;
573 :
574 18884: return Emitted;
575 : }
576 :
577 : /// Destructor - The dtor emits the diagnostic if it hasn't already
578 : /// been emitted.
579 34637: ~DiagnosticBuilder() { Emit(); }
580 :
581 : /// isActive - Determine whether this diagnostic is still active.
582 73: bool isActive() const { return DiagObj != 0; }
583 :
584 : /// Operator bool: conversion of DiagnosticBuilder to bool always returns
585 : /// true. This allows is to be used in boolean error contexts like:
586 : /// return Diag(...);
587 120: operator bool() const { return true; }
588 :
589 770: void AddString(llvm::StringRef S) const {
590 : assert(NumArgs < Diagnostic::MaxArguments &&
770: branch 1 taken
0: branch 1 not taken
591 770: "Too many arguments to diagnostic!");
770: branch 0 taken
0: branch 1 not taken
592 770: if (DiagObj) {
593 770: DiagObj->DiagArgumentsKind[NumArgs] = Diagnostic::ak_std_string;
594 770: DiagObj->DiagArgumentsStr[NumArgs++] = S;
595 : }
596 770: }
597 :
598 17626: void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const {
599 : assert(NumArgs < Diagnostic::MaxArguments &&
0: branch 1 not taken
17626: branch 1 taken
600 17626: "Too many arguments to diagnostic!");
17621: branch 0 taken
5: branch 1 taken
601 17626: if (DiagObj) {
602 17621: DiagObj->DiagArgumentsKind[NumArgs] = Kind;
603 17621: DiagObj->DiagArgumentsVal[NumArgs++] = V;
604 : }
605 17626: }
606 :
607 4392: void AddSourceRange(const SourceRange &R) const {
608 : assert(NumRanges <
609 : sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) &&
4392: branch 1 taken
0: branch 1 not taken
610 4392: "Too many arguments to diagnostic!");
4371: branch 0 taken
21: branch 1 taken
611 4392: if (DiagObj)
612 4371: DiagObj->DiagRanges[NumRanges++] = R;
613 4392: }
614 :
615 883: void AddCodeModificationHint(const CodeModificationHint &Hint) const {
0: branch 2 not taken
0: branch 2 not taken
616 883: if (Hint.isNull())
617 298: return;
618 :
619 : assert(NumCodeModificationHints < Diagnostic::MaxCodeModificationHints &&
0: branch 0 not taken
585: branch 1 taken
620 585: "Too many code modification hints!");
585: branch 0 taken
0: branch 1 not taken
621 585: if (DiagObj)
622 585: DiagObj->CodeModificationHints[NumCodeModificationHints++] = Hint;
623 : }
624 : };
625 :
626 : inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
627 770: llvm::StringRef S) {
628 770: DB.AddString(S);
629 770: return DB;
630 : }
631 :
632 : inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
633 727: const char *Str) {
634 : DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str),
635 727: Diagnostic::ak_c_string);
636 727: return DB;
637 : }
638 :
639 786: inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) {
640 786: DB.AddTaggedVal(I, Diagnostic::ak_sint);
641 786: return DB;
642 : }
643 :
644 487: inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,bool I) {
645 487: DB.AddTaggedVal(I, Diagnostic::ak_sint);
646 487: return DB;
647 : }
648 :
649 : inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
650 881: unsigned I) {
651 881: DB.AddTaggedVal(I, Diagnostic::ak_uint);
652 881: return DB;
653 : }
654 :
655 : inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
656 445: const IdentifierInfo *II) {
657 : DB.AddTaggedVal(reinterpret_cast<intptr_t>(II),
658 445: Diagnostic::ak_identifierinfo);
659 445: return DB;
660 : }
661 :
662 : // Adds a DeclContext to the diagnostic. The enable_if template magic is here
663 : // so that we only match those arguments that are (statically) DeclContexts;
664 : // other arguments that derive from DeclContext (e.g., RecordDecls) will not
665 : // match.
666 : template<typename T>
667 : inline
668 : typename llvm::enable_if<llvm::is_same<T, DeclContext>,
669 : const DiagnosticBuilder &>::type
670 89: operator<<(const DiagnosticBuilder &DB, T *DC) {
671 89: DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC),
672 : Diagnostic::ak_declcontext);
673 89: return DB;
674 : }
675 :
676 : inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
677 4270: const SourceRange &R) {
678 4270: DB.AddSourceRange(R);
679 4270: return DB;
680 : }
681 :
682 : inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
683 871: const CodeModificationHint &Hint) {
684 871: DB.AddCodeModificationHint(Hint);
685 871: return DB;
686 : }
687 :
688 : /// Report - Issue the message to the client. DiagID is a member of the
689 : /// diag::kind enum. This actually returns a new instance of DiagnosticBuilder
690 : /// which emits the diagnostics (through ProcessDiag) when it is destroyed.
691 18884: inline DiagnosticBuilder Diagnostic::Report(FullSourceLoc Loc, unsigned DiagID){
18884: branch 1 taken
0: branch 1 not taken
692 18884: assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
693 18884: CurDiagLoc = Loc;
694 18884: CurDiagID = DiagID;
695 18884: return DiagnosticBuilder(this);
696 : }
697 61: inline DiagnosticBuilder Diagnostic::Report(unsigned DiagID) {
698 61: return Report(FullSourceLoc(), DiagID);
699 : }
700 :
701 : //===----------------------------------------------------------------------===//
702 : // DiagnosticInfo
703 : //===----------------------------------------------------------------------===//
704 :
705 : /// DiagnosticInfo - This is a little helper class (which is basically a smart
706 : /// pointer that forward info from Diagnostic) that allows clients to enquire
707 : /// about the currently in-flight diagnostic.
708 : class DiagnosticInfo {
709 : const Diagnostic *DiagObj;
710 : public:
711 18884: explicit DiagnosticInfo(const Diagnostic *DO) : DiagObj(DO) {}
712 :
713 12595: const Diagnostic *getDiags() const { return DiagObj; }
714 26554: unsigned getID() const { return DiagObj->CurDiagID; }
715 20002: const FullSourceLoc &getLocation() const { return DiagObj->CurDiagLoc; }
716 :
717 24725: unsigned getNumArgs() const { return DiagObj->NumDiagArgs; }
718 :
719 : /// getArgKind - Return the kind of the specified index. Based on the kind
720 : /// of argument, the accessors below can be used to get the value.
721 24725: Diagnostic::ArgumentKind getArgKind(unsigned Idx) const {
722 24725: assert(Idx < getNumArgs() && "Argument index out of range!");
723 24725: return (Diagnostic::ArgumentKind)DiagObj->DiagArgumentsKind[Idx];
724 : }
725 :
726 : /// getArgStdStr - Return the provided argument string specified by Idx.
727 1336: const std::string &getArgStdStr(unsigned Idx) const {
728 : assert(getArgKind(Idx) == Diagnostic::ak_std_string &&
729 1336: "invalid argument accessor!");
730 1336: return DiagObj->DiagArgumentsStr[Idx];
731 : }
732 :
733 : /// getArgCStr - Return the specified C string argument.
734 445: const char *getArgCStr(unsigned Idx) const {
735 : assert(getArgKind(Idx) == Diagnostic::ak_c_string &&
736 445: "invalid argument accessor!");
737 445: return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]);
738 : }
739 :
740 : /// getArgSInt - Return the specified signed integer argument.
741 1176: int getArgSInt(unsigned Idx) const {
742 : assert(getArgKind(Idx) == Diagnostic::ak_sint &&
743 1176: "invalid argument accessor!");
744 1176: return (int)DiagObj->DiagArgumentsVal[Idx];
745 : }
746 :
747 : /// getArgUInt - Return the specified unsigned integer argument.
748 993: unsigned getArgUInt(unsigned Idx) const {
749 : assert(getArgKind(Idx) == Diagnostic::ak_uint &&
750 993: "invalid argument accessor!");
751 993: return (unsigned)DiagObj->DiagArgumentsVal[Idx];
752 : }
753 :
754 : /// getArgIdentifier - Return the specified IdentifierInfo argument.
755 383: const IdentifierInfo *getArgIdentifier(unsigned Idx) const {
756 : assert(getArgKind(Idx) == Diagnostic::ak_identifierinfo &&
757 383: "invalid argument accessor!");
758 383: return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]);
759 : }
760 :
761 : /// getRawArg - Return the specified non-string argument in an opaque form.
762 12150: intptr_t getRawArg(unsigned Idx) const {
763 : assert(getArgKind(Idx) != Diagnostic::ak_std_string &&
764 12150: "invalid argument accessor!");
765 12150: return DiagObj->DiagArgumentsVal[Idx];
766 : }
767 :
768 :
769 : /// getNumRanges - Return the number of source ranges associated with this
770 : /// diagnostic.
771 884: unsigned getNumRanges() const {
772 884: return DiagObj->NumDiagRanges;
773 : }
774 :
775 240: SourceRange getRange(unsigned Idx) const {
776 240: assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!");
777 240: return DiagObj->DiagRanges[Idx];
778 : }
779 :
780 1691: unsigned getNumCodeModificationHints() const {
781 1691: return DiagObj->NumCodeModificationHints;
782 : }
783 :
784 241: const CodeModificationHint &getCodeModificationHint(unsigned Idx) const {
785 241: return DiagObj->CodeModificationHints[Idx];
786 : }
787 :
788 634: const CodeModificationHint *getCodeModificationHints() const {
789 : return DiagObj->NumCodeModificationHints?
790 634: &DiagObj->CodeModificationHints[0] : 0;
791 : }
792 :
793 : /// FormatDiagnostic - Format this diagnostic into a string, substituting the
794 : /// formal arguments into the %0 slots. The result is appended onto the Str
795 : /// array.
796 : void FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const;
797 :
798 : /// FormatDiagnostic - Format the given format-string into the
799 : /// output buffer using the arguments stored in this diagnostic.
800 : void FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
801 : llvm::SmallVectorImpl<char> &OutStr) const;
802 :
803 : /// Serialize - Serialize the given diagnostic (with its diagnostic
804 : /// level) to the given stream. Serialization is a lossy operation,
805 : /// since the specific diagnostic ID and any macro-instantiation
806 : /// information is lost.
807 : void Serialize(Diagnostic::Level DiagLevel, llvm::raw_ostream &OS) const;
808 : };
809 :
810 : /// DiagnosticClient - This is an abstract interface implemented by clients of
811 : /// the front-end, which formats and prints fully processed diagnostics.
812 11983: class DiagnosticClient {
813 : public:
814 : virtual ~DiagnosticClient();
815 :
816 : /// BeginSourceFile - Callback to inform the diagnostic client that processing
817 : /// of a source file is beginning.
818 : ///
819 : /// Note that diagnostics may be emitted outside the processing of a source
820 : /// file, for example during the parsing of command line options. However,
821 : /// diagnostics with source range information are required to only be emitted
822 : /// in between BeginSourceFile() and EndSourceFile().
823 : ///
824 : /// \arg LO - The language options for the source file being processed.
825 : /// \arg PP - The preprocessor object being used for the source; this optional
826 : /// and may not be present, for example when processing AST source files.
827 : virtual void BeginSourceFile(const LangOptions &LangOpts,
828 52: const Preprocessor *PP = 0) {}
829 :
830 : /// EndSourceFile - Callback to inform the diagnostic client that processing
831 : /// of a source file has ended. The diagnostic client should assume that any
832 : /// objects made available via \see BeginSourceFile() are inaccessible.
833 52: virtual void EndSourceFile() {}
834 :
835 : /// IncludeInDiagnosticCounts - This method (whose default implementation
836 : /// returns true) indicates whether the diagnostics handled by this
837 : /// DiagnosticClient should be included in the number of diagnostics reported
838 : /// by Diagnostic.
839 : virtual bool IncludeInDiagnosticCounts() const;
840 :
841 : /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
842 : /// capturing it to a log as needed.
843 : virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
844 : const DiagnosticInfo &Info) = 0;
845 : };
846 :
847 : } // end namespace clang
848 :
849 : #endif
Generated: 2010-02-10 01:31 by zcov