• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- DiagnosticIDs.h - Diagnostic IDs 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 IDs-related interfaces.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_DIAGNOSTICIDS_H
15 #define LLVM_CLANG_DIAGNOSTICIDS_H
16 
17 #include "llvm/ADT/IntrusiveRefCntPtr.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "clang/Basic/LLVM.h"
20 
21 namespace llvm {
22   template<typename T, unsigned> class SmallVector;
23 }
24 
25 namespace clang {
26   class DiagnosticsEngine;
27   class SourceLocation;
28   struct WarningOption;
29 
30   // Import the diagnostic enums themselves.
31   namespace diag {
32     // Start position for diagnostics.
33     enum {
34       DIAG_START_DRIVER        =                               300,
35       DIAG_START_FRONTEND      = DIAG_START_DRIVER          +  100,
36       DIAG_START_SERIALIZATION = DIAG_START_FRONTEND        +  100,
37       DIAG_START_LEX           = DIAG_START_SERIALIZATION   +  120,
38       DIAG_START_PARSE         = DIAG_START_LEX             +  300,
39       DIAG_START_AST           = DIAG_START_PARSE           +  400,
40       DIAG_START_SEMA          = DIAG_START_AST             +  100,
41       DIAG_START_ANALYSIS      = DIAG_START_SEMA            + 3000,
42       DIAG_UPPER_LIMIT         = DIAG_START_ANALYSIS        +  100
43     };
44 
45     class CustomDiagInfo;
46 
47     /// diag::kind - All of the diagnostics that can be emitted by the frontend.
48     typedef unsigned kind;
49 
50     // Get typedefs for common diagnostics.
51     enum {
52 #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
53              SFINAE,ACCESS,CATEGORY,NOWERROR,SHOWINSYSHEADER) ENUM,
54 #include "clang/Basic/DiagnosticCommonKinds.inc"
55       NUM_BUILTIN_COMMON_DIAGNOSTICS
56 #undef DIAG
57     };
58 
59     /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
60     /// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR
61     /// (emit as an error).  It allows clients to map errors to
62     /// MAP_ERROR/MAP_DEFAULT or MAP_FATAL (stop emitting diagnostics after this
63     /// one).
64     enum Mapping {
65       // NOTE: 0 means "uncomputed".
66       MAP_IGNORE  = 1,     //< Map this diagnostic to nothing, ignore it.
67       MAP_WARNING = 2,     //< Map this diagnostic to a warning.
68       MAP_ERROR   = 3,     //< Map this diagnostic to an error.
69       MAP_FATAL   = 4      //< Map this diagnostic to a fatal error.
70     };
71   }
72 
73 class DiagnosticMappingInfo {
74   unsigned Mapping : 3;
75   unsigned IsUser : 1;
76   unsigned IsPragma : 1;
77   unsigned HasShowInSystemHeader : 1;
78   unsigned HasNoWarningAsError : 1;
79   unsigned HasNoErrorAsFatal : 1;
80 
81 public:
Make(diag::Mapping Mapping,bool IsUser,bool IsPragma)82   static DiagnosticMappingInfo Make(diag::Mapping Mapping, bool IsUser,
83                                     bool IsPragma) {
84     DiagnosticMappingInfo Result;
85     Result.Mapping = Mapping;
86     Result.IsUser = IsUser;
87     Result.IsPragma = IsPragma;
88     Result.HasShowInSystemHeader = 0;
89     Result.HasNoWarningAsError = 0;
90     Result.HasNoErrorAsFatal = 0;
91     return Result;
92   }
93 
getMapping()94   diag::Mapping getMapping() const { return diag::Mapping(Mapping); }
setMapping(diag::Mapping Value)95   void setMapping(diag::Mapping Value) { Mapping = Value; }
96 
isUser()97   bool isUser() const { return IsUser; }
isPragma()98   bool isPragma() const { return IsPragma; }
99 
hasShowInSystemHeader()100   bool hasShowInSystemHeader() const { return HasShowInSystemHeader; }
setShowInSystemHeader(bool Value)101   void setShowInSystemHeader(bool Value) { HasShowInSystemHeader = Value; }
102 
hasNoWarningAsError()103   bool hasNoWarningAsError() const { return HasNoWarningAsError; }
setNoWarningAsError(bool Value)104   void setNoWarningAsError(bool Value) { HasNoWarningAsError = Value; }
105 
hasNoErrorAsFatal()106   bool hasNoErrorAsFatal() const { return HasNoErrorAsFatal; }
setNoErrorAsFatal(bool Value)107   void setNoErrorAsFatal(bool Value) { HasNoErrorAsFatal = Value; }
108 };
109 
110 /// \brief Used for handling and querying diagnostic IDs. Can be used and shared
111 /// by multiple Diagnostics for multiple translation units.
112 class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
113 public:
114   /// Level - The level of the diagnostic, after it has been through mapping.
115   enum Level {
116     Ignored, Note, Warning, Error, Fatal
117   };
118 
119 private:
120   /// CustomDiagInfo - Information for uniquing and looking up custom diags.
121   diag::CustomDiagInfo *CustomDiagInfo;
122 
123 public:
124   DiagnosticIDs();
125   ~DiagnosticIDs();
126 
127   /// getCustomDiagID - Return an ID for a diagnostic with the specified message
128   /// and level.  If this is the first request for this diagnosic, it is
129   /// registered and created, otherwise the existing ID is returned.
130   unsigned getCustomDiagID(Level L, StringRef Message);
131 
132   //===--------------------------------------------------------------------===//
133   // Diagnostic classification and reporting interfaces.
134   //
135 
136   /// getDescription - Given a diagnostic ID, return a description of the
137   /// issue.
138   StringRef getDescription(unsigned DiagID) const;
139 
140   /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic level
141   /// of the specified diagnostic ID is a Warning or Extension.  This only works
142   /// on builtin diagnostics, not custom ones, and is not legal to call on
143   /// NOTEs.
144   static bool isBuiltinWarningOrExtension(unsigned DiagID);
145 
146   /// \brief Return true if the specified diagnostic is mapped to errors by
147   /// default.
148   static bool isDefaultMappingAsError(unsigned DiagID);
149 
150   /// \brief Determine whether the given built-in diagnostic ID is a
151   /// Note.
152   static bool isBuiltinNote(unsigned DiagID);
153 
154   /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
155   /// ID is for an extension of some sort.
156   ///
isBuiltinExtensionDiag(unsigned DiagID)157   static bool isBuiltinExtensionDiag(unsigned DiagID) {
158     bool ignored;
159     return isBuiltinExtensionDiag(DiagID, ignored);
160   }
161 
162   /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
163   /// ID is for an extension of some sort.  This also returns EnabledByDefault,
164   /// which is set to indicate whether the diagnostic is ignored by default (in
165   /// which case -pedantic enables it) or treated as a warning/error by default.
166   ///
167   static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault);
168 
169 
170   /// getWarningOptionForDiag - Return the lowest-level warning option that
171   /// enables the specified diagnostic.  If there is no -Wfoo flag that controls
172   /// the diagnostic, this returns null.
173   static StringRef getWarningOptionForDiag(unsigned DiagID);
174 
175   /// getCategoryNumberForDiag - Return the category number that a specified
176   /// DiagID belongs to, or 0 if no category.
177   static unsigned getCategoryNumberForDiag(unsigned DiagID);
178 
179   /// getNumberOfCategories - Return the number of categories
180   static unsigned getNumberOfCategories();
181 
182   /// getCategoryNameFromID - Given a category ID, return the name of the
183   /// category.
184   static StringRef getCategoryNameFromID(unsigned CategoryID);
185 
186   /// isARCDiagnostic - Return true if a given diagnostic falls into an
187   /// ARC diagnostic category;
188   static bool isARCDiagnostic(unsigned DiagID);
189 
190   /// \brief Enumeration describing how the the emission of a diagnostic should
191   /// be treated when it occurs during C++ template argument deduction.
192   enum SFINAEResponse {
193     /// \brief The diagnostic should not be reported, but it should cause
194     /// template argument deduction to fail.
195     ///
196     /// The vast majority of errors that occur during template argument
197     /// deduction fall into this category.
198     SFINAE_SubstitutionFailure,
199 
200     /// \brief The diagnostic should be suppressed entirely.
201     ///
202     /// Warnings generally fall into this category.
203     SFINAE_Suppress,
204 
205     /// \brief The diagnostic should be reported.
206     ///
207     /// The diagnostic should be reported. Various fatal errors (e.g.,
208     /// template instantiation depth exceeded) fall into this category.
209     SFINAE_Report,
210 
211     /// \brief The diagnostic is an access-control diagnostic, which will be
212     /// substitution failures in some contexts and reported in others.
213     SFINAE_AccessControl
214   };
215 
216   /// \brief Determines whether the given built-in diagnostic ID is
217   /// for an error that is suppressed if it occurs during C++ template
218   /// argument deduction.
219   ///
220   /// When an error is suppressed due to SFINAE, the template argument
221   /// deduction fails but no diagnostic is emitted. Certain classes of
222   /// errors, such as those errors that involve C++ access control,
223   /// are not SFINAE errors.
224   static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID);
225 
226   /// \brief Get the set of all diagnostic IDs in the group with the given name.
227   ///
228   /// \param Diags [out] - On return, the diagnostics in the group.
229   /// \returns True if the given group is unknown, false otherwise.
230   bool getDiagnosticsInGroup(StringRef Group,
231                              llvm::SmallVectorImpl<diag::kind> &Diags) const;
232 
233   /// \brief Get the set of all diagnostic IDs.
234   void getAllDiagnostics(llvm::SmallVectorImpl<diag::kind> &Diags) const;
235 
236   /// \brief Get the warning option with the closest edit distance to the given
237   /// group name.
238   static StringRef getNearestWarningOption(StringRef Group);
239 
240 private:
241   /// \brief Get the set of all diagnostic IDs in the given group.
242   ///
243   /// \param Diags [out] - On return, the diagnostics in the group.
244   void getDiagnosticsInGroup(const WarningOption *Group,
245                              llvm::SmallVectorImpl<diag::kind> &Diags) const;
246 
247   /// \brief Based on the way the client configured the DiagnosticsEngine
248   /// object, classify the specified diagnostic ID into a Level, consumable by
249   /// the DiagnosticClient.
250   ///
251   /// \param Loc The source location we are interested in finding out the
252   /// diagnostic state. Can be null in order to query the latest state.
253   DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
254                                           const DiagnosticsEngine &Diag) const;
255 
256   /// getDiagnosticLevel - This is an internal implementation helper used when
257   /// DiagClass is already known.
258   DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID,
259                                           unsigned DiagClass,
260                                           SourceLocation Loc,
261                                           const DiagnosticsEngine &Diag) const;
262 
263   /// ProcessDiag - This is the method used to report a diagnostic that is
264   /// finally fully formed.
265   ///
266   /// \returns true if the diagnostic was emitted, false if it was
267   /// suppressed.
268   bool ProcessDiag(DiagnosticsEngine &Diag) const;
269 
270   /// \brief Whether the diagnostic may leave the AST in a state where some
271   /// invariants can break.
272   bool isUnrecoverable(unsigned DiagID) const;
273 
274   friend class DiagnosticsEngine;
275 };
276 
277 }  // end namespace clang
278 
279 #endif
280