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