Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 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" |
Chris Lattner | 686775d | 2011-07-20 06:58:45 +0000 | [diff] [blame] | 19 | #include "clang/Basic/LLVM.h" |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 20 | |
Daniel Dunbar | 3f83946 | 2011-09-29 01:47:16 +0000 | [diff] [blame^] | 21 | namespace llvm { |
| 22 | template<typename T, unsigned> class SmallVector; |
| 23 | } |
| 24 | |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 25 | namespace clang { |
David Blaikie | d6471f7 | 2011-09-25 23:23:43 +0000 | [diff] [blame] | 26 | class DiagnosticsEngine; |
Argyrios Kyrtzidis | 0827408 | 2010-12-15 18:44:22 +0000 | [diff] [blame] | 27 | class SourceLocation; |
Daniel Dunbar | 3f83946 | 2011-09-29 01:47:16 +0000 | [diff] [blame^] | 28 | struct WarningOption; |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 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, |
Fariborz Jahanian | f84109e | 2011-01-07 18:59:25 +0000 | [diff] [blame] | 36 | DIAG_START_LEX = DIAG_START_FRONTEND + 120, |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 37 | DIAG_START_PARSE = DIAG_START_LEX + 300, |
| 38 | DIAG_START_AST = DIAG_START_PARSE + 300, |
| 39 | DIAG_START_SEMA = DIAG_START_AST + 100, |
Chandler Carruth | d24eda8 | 2011-02-16 19:41:58 +0000 | [diff] [blame] | 40 | DIAG_START_ANALYSIS = DIAG_START_SEMA + 3000, |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 41 | DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100 |
| 42 | }; |
| 43 | |
| 44 | class CustomDiagInfo; |
| 45 | |
| 46 | /// diag::kind - All of the diagnostics that can be emitted by the frontend. |
| 47 | typedef unsigned kind; |
| 48 | |
| 49 | // Get typedefs for common diagnostics. |
| 50 | enum { |
Douglas Gregor | 7d2b8c1 | 2011-04-15 22:04:17 +0000 | [diff] [blame] | 51 | #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ |
Daniel Dunbar | 4213df3 | 2011-09-29 00:34:06 +0000 | [diff] [blame] | 52 | SFINAE,ACCESS,CATEGORY,NOWERROR,SHOWINSYSHEADER,BRIEF,FULL) ENUM, |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 53 | #include "clang/Basic/DiagnosticCommonKinds.inc" |
| 54 | NUM_BUILTIN_COMMON_DIAGNOSTICS |
| 55 | #undef DIAG |
| 56 | }; |
| 57 | |
| 58 | /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs |
| 59 | /// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR |
| 60 | /// (emit as an error). It allows clients to map errors to |
| 61 | /// MAP_ERROR/MAP_DEFAULT or MAP_FATAL (stop emitting diagnostics after this |
| 62 | /// one). |
| 63 | enum Mapping { |
| 64 | // NOTE: 0 means "uncomputed". |
| 65 | MAP_IGNORE = 1, //< Map this diagnostic to nothing, ignore it. |
| 66 | MAP_WARNING = 2, //< Map this diagnostic to a warning. |
| 67 | MAP_ERROR = 3, //< Map this diagnostic to an error. |
| 68 | MAP_FATAL = 4, //< Map this diagnostic to a fatal error. |
| 69 | |
| 70 | /// Map this diagnostic to "warning", but make it immune to -Werror. This |
| 71 | /// happens when you specify -Wno-error=foo. |
| 72 | MAP_WARNING_NO_WERROR = 5, |
Argyrios Kyrtzidis | 144bc08 | 2011-04-21 23:08:23 +0000 | [diff] [blame] | 73 | /// Map this diagnostic to "warning", but make it immune to |
| 74 | /// -Wno-system-headers. |
| 75 | MAP_WARNING_SHOW_IN_SYSTEM_HEADER = 6, |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 76 | /// Map this diagnostic to "error", but make it immune to -Wfatal-errors. |
| 77 | /// This happens for -Wno-fatal-errors=foo. |
Argyrios Kyrtzidis | 144bc08 | 2011-04-21 23:08:23 +0000 | [diff] [blame] | 78 | MAP_ERROR_NO_WFATAL = 7 |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 79 | }; |
| 80 | } |
| 81 | |
Daniel Dunbar | b1c99c6 | 2011-09-29 01:30:00 +0000 | [diff] [blame] | 82 | class DiagnosticMappingInfo { |
| 83 | unsigned Mapping : 3; |
| 84 | unsigned IsUser : 1; |
| 85 | unsigned IsPragma : 1; |
| 86 | |
| 87 | public: |
| 88 | static DiagnosticMappingInfo MakeUnset() { |
| 89 | DiagnosticMappingInfo Result; |
| 90 | Result.Mapping = Result.IsUser = Result.IsPragma = 0; |
| 91 | return Result; |
| 92 | } |
| 93 | |
| 94 | static DiagnosticMappingInfo MakeInfo(diag::Mapping Mapping, |
| 95 | bool IsUser, bool IsPragma) { |
| 96 | DiagnosticMappingInfo Result; |
| 97 | Result.Mapping = Mapping; |
| 98 | Result.IsUser = IsUser; |
| 99 | Result.IsPragma = IsPragma; |
| 100 | return Result; |
| 101 | } |
| 102 | |
| 103 | diag::Mapping getMapping() const { return diag::Mapping(Mapping); } |
| 104 | bool isUser() const { return IsUser; } |
| 105 | bool isPragma() const { return IsPragma; } |
| 106 | |
| 107 | bool isUnset() const { return Mapping == 0; } |
| 108 | }; |
| 109 | |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 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 llvm::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. |
Chris Lattner | 686775d | 2011-07-20 06:58:45 +0000 | [diff] [blame] | 130 | unsigned getCustomDiagID(Level L, StringRef Message); |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 131 | |
| 132 | //===--------------------------------------------------------------------===// |
| 133 | // Diagnostic classification and reporting interfaces. |
| 134 | // |
| 135 | |
| 136 | /// getDescription - Given a diagnostic ID, return a description of the |
| 137 | /// issue. |
Chris Lattner | 686775d | 2011-07-20 06:58:45 +0000 | [diff] [blame] | 138 | StringRef getDescription(unsigned DiagID) const; |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 139 | |
Daniel Dunbar | 80d572d | 2011-09-29 00:53:50 +0000 | [diff] [blame] | 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. |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 144 | static bool isBuiltinWarningOrExtension(unsigned DiagID); |
| 145 | |
Daniel Dunbar | 76101cf | 2011-09-29 01:01:08 +0000 | [diff] [blame] | 146 | /// \brief Return true if the specified diagnostic is mapped to errors by |
| 147 | /// default. |
| 148 | static bool isDefaultMappingAsError(unsigned DiagID); |
| 149 | |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 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 | /// |
| 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. |
Chris Lattner | 686775d | 2011-07-20 06:58:45 +0000 | [diff] [blame] | 173 | static StringRef getWarningOptionForDiag(unsigned DiagID); |
Argyrios Kyrtzidis | 477aab6 | 2011-05-25 05:05:01 +0000 | [diff] [blame] | 174 | |
Douglas Gregor | 7d2b8c1 | 2011-04-15 22:04:17 +0000 | [diff] [blame] | 175 | /// getCategoryNumberForDiag - Return the category number that a specified |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 176 | /// DiagID belongs to, or 0 if no category. |
| 177 | static unsigned getCategoryNumberForDiag(unsigned DiagID); |
| 178 | |
Argyrios Kyrtzidis | 477aab6 | 2011-05-25 05:05:01 +0000 | [diff] [blame] | 179 | /// getNumberOfCategories - Return the number of categories |
| 180 | static unsigned getNumberOfCategories(); |
| 181 | |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 182 | /// getCategoryNameFromID - Given a category ID, return the name of the |
| 183 | /// category. |
Chris Lattner | 686775d | 2011-07-20 06:58:45 +0000 | [diff] [blame] | 184 | static StringRef getCategoryNameFromID(unsigned CategoryID); |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 185 | |
| 186 | /// \brief Enumeration describing how the the emission of a diagnostic should |
| 187 | /// be treated when it occurs during C++ template argument deduction. |
| 188 | enum SFINAEResponse { |
| 189 | /// \brief The diagnostic should not be reported, but it should cause |
| 190 | /// template argument deduction to fail. |
| 191 | /// |
| 192 | /// The vast majority of errors that occur during template argument |
| 193 | /// deduction fall into this category. |
| 194 | SFINAE_SubstitutionFailure, |
| 195 | |
| 196 | /// \brief The diagnostic should be suppressed entirely. |
| 197 | /// |
| 198 | /// Warnings generally fall into this category. |
| 199 | SFINAE_Suppress, |
| 200 | |
| 201 | /// \brief The diagnostic should be reported. |
| 202 | /// |
| 203 | /// The diagnostic should be reported. Various fatal errors (e.g., |
| 204 | /// template instantiation depth exceeded) fall into this category. |
Douglas Gregor | 418df34 | 2011-01-27 21:06:28 +0000 | [diff] [blame] | 205 | SFINAE_Report, |
| 206 | |
| 207 | /// \brief The diagnostic is an access-control diagnostic, which will be |
| 208 | /// substitution failures in some contexts and reported in others. |
| 209 | SFINAE_AccessControl |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 210 | }; |
| 211 | |
| 212 | /// \brief Determines whether the given built-in diagnostic ID is |
| 213 | /// for an error that is suppressed if it occurs during C++ template |
| 214 | /// argument deduction. |
| 215 | /// |
| 216 | /// When an error is suppressed due to SFINAE, the template argument |
| 217 | /// deduction fails but no diagnostic is emitted. Certain classes of |
| 218 | /// errors, such as those errors that involve C++ access control, |
| 219 | /// are not SFINAE errors. |
| 220 | static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID); |
| 221 | |
Douglas Gregor | 7d2b8c1 | 2011-04-15 22:04:17 +0000 | [diff] [blame] | 222 | /// getName - Given a diagnostic ID, return its name |
Chris Lattner | 686775d | 2011-07-20 06:58:45 +0000 | [diff] [blame] | 223 | static StringRef getName(unsigned DiagID); |
Douglas Gregor | 7d2b8c1 | 2011-04-15 22:04:17 +0000 | [diff] [blame] | 224 | |
| 225 | /// getIdFromName - Given a diagnostic name, return its ID, or 0 |
Chris Lattner | 686775d | 2011-07-20 06:58:45 +0000 | [diff] [blame] | 226 | static unsigned getIdFromName(StringRef Name); |
Douglas Gregor | 7d2b8c1 | 2011-04-15 22:04:17 +0000 | [diff] [blame] | 227 | |
| 228 | /// getBriefExplanation - Given a diagnostic ID, return a brief explanation |
| 229 | /// of the issue |
Chris Lattner | 686775d | 2011-07-20 06:58:45 +0000 | [diff] [blame] | 230 | static StringRef getBriefExplanation(unsigned DiagID); |
Douglas Gregor | 7d2b8c1 | 2011-04-15 22:04:17 +0000 | [diff] [blame] | 231 | |
| 232 | /// getFullExplanation - Given a diagnostic ID, return a full explanation |
| 233 | /// of the issue |
Chris Lattner | 686775d | 2011-07-20 06:58:45 +0000 | [diff] [blame] | 234 | static StringRef getFullExplanation(unsigned DiagID); |
Ted Kremenek | 6948bc4 | 2011-08-09 03:39:14 +0000 | [diff] [blame] | 235 | |
| 236 | /// Iterator class used for traversing all statically declared |
| 237 | /// diagnostics. |
| 238 | class diag_iterator { |
| 239 | const void *impl; |
| 240 | |
| 241 | friend class DiagnosticIDs; |
Bill Wendling | cb9657c | 2011-08-12 01:29:32 +0000 | [diff] [blame] | 242 | diag_iterator(const void *im) : impl(im) {} |
Ted Kremenek | 6948bc4 | 2011-08-09 03:39:14 +0000 | [diff] [blame] | 243 | public: |
| 244 | diag_iterator &operator++(); |
| 245 | bool operator==(const diag_iterator &x) const { return impl == x.impl; } |
| 246 | bool operator!=(const diag_iterator &x) const { return impl != x.impl; } |
| 247 | |
| 248 | llvm::StringRef getDiagName() const; |
| 249 | unsigned getDiagID() const; |
| 250 | }; |
| 251 | |
| 252 | static diag_iterator diags_begin(); |
| 253 | static diag_iterator diags_end(); |
Douglas Gregor | 7d2b8c1 | 2011-04-15 22:04:17 +0000 | [diff] [blame] | 254 | |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 255 | private: |
Daniel Dunbar | 3f83946 | 2011-09-29 01:47:16 +0000 | [diff] [blame^] | 256 | /// \brief Get the set of all diagnostic IDs in the group with the given name. |
| 257 | /// |
| 258 | /// \param Diags [out] - On return, the diagnostics in the group. |
| 259 | /// \returns True if the given group is unknown, false otherwise. |
| 260 | bool getDiagnosticsInGroup(StringRef Group, |
| 261 | llvm::SmallVectorImpl<diag::kind> &Diags) const; |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 262 | |
Daniel Dunbar | 3f83946 | 2011-09-29 01:47:16 +0000 | [diff] [blame^] | 263 | /// \brief Get the set of all diagnostic IDs in the given group. |
| 264 | /// |
| 265 | /// \param Diags [out] - On return, the diagnostics in the group. |
| 266 | void getDiagnosticsInGroup(const WarningOption *Group, |
| 267 | llvm::SmallVectorImpl<diag::kind> &Diags) const; |
| 268 | |
David Blaikie | d6471f7 | 2011-09-25 23:23:43 +0000 | [diff] [blame] | 269 | /// \brief Based on the way the client configured the DiagnosticsEngine |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 270 | /// object, classify the specified diagnostic ID into a Level, consumable by |
| 271 | /// the DiagnosticClient. |
Argyrios Kyrtzidis | 0827408 | 2010-12-15 18:44:22 +0000 | [diff] [blame] | 272 | /// |
| 273 | /// \param Loc The source location we are interested in finding out the |
| 274 | /// diagnostic state. Can be null in order to query the latest state. |
| 275 | DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, |
Daniel Dunbar | 1656aae | 2011-09-29 01:20:28 +0000 | [diff] [blame] | 276 | const DiagnosticsEngine &Diag) const; |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 277 | |
| 278 | /// getDiagnosticLevel - This is an internal implementation helper used when |
| 279 | /// DiagClass is already known. |
| 280 | DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID, |
| 281 | unsigned DiagClass, |
Argyrios Kyrtzidis | 0827408 | 2010-12-15 18:44:22 +0000 | [diff] [blame] | 282 | SourceLocation Loc, |
Daniel Dunbar | 1656aae | 2011-09-29 01:20:28 +0000 | [diff] [blame] | 283 | const DiagnosticsEngine &Diag) const; |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 284 | |
| 285 | /// ProcessDiag - This is the method used to report a diagnostic that is |
| 286 | /// finally fully formed. |
| 287 | /// |
| 288 | /// \returns true if the diagnostic was emitted, false if it was |
| 289 | /// suppressed. |
David Blaikie | d6471f7 | 2011-09-25 23:23:43 +0000 | [diff] [blame] | 290 | bool ProcessDiag(DiagnosticsEngine &Diag) const; |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 291 | |
John McCall | add80bb | 2011-06-15 22:11:51 +0000 | [diff] [blame] | 292 | /// \brief Whether the diagnostic may leave the AST in a state where some |
| 293 | /// invariants can break. |
| 294 | bool isUnrecoverable(unsigned DiagID) const; |
| 295 | |
David Blaikie | d6471f7 | 2011-09-25 23:23:43 +0000 | [diff] [blame] | 296 | friend class DiagnosticsEngine; |
Argyrios Kyrtzidis | 33e4e70 | 2010-11-18 20:06:41 +0000 | [diff] [blame] | 297 | }; |
| 298 | |
| 299 | } // end namespace clang |
| 300 | |
| 301 | #endif |