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_BASIC_DIAGNOSTICIDS_H 16 #define LLVM_CLANG_BASIC_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 + 500, 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 /// Flavors of diagnostics we can emit. Used to filter for a particular 72 /// kind of diagnostic (for instance, for -W/-R flags). 73 enum class Flavor { 74 WarningOrError, ///< A diagnostic that indicates a problem or potential 75 ///< problem. Can be made fatal by -Werror. 76 Remark ///< A diagnostic that indicates normal progress through 77 ///< compilation. 78 }; 79 } 80 81 class DiagnosticMapping { 82 unsigned Severity : 3; 83 unsigned IsUser : 1; 84 unsigned IsPragma : 1; 85 unsigned HasNoWarningAsError : 1; 86 unsigned HasNoErrorAsFatal : 1; 87 88 public: Make(diag::Severity Severity,bool IsUser,bool IsPragma)89 static DiagnosticMapping Make(diag::Severity Severity, bool IsUser, 90 bool IsPragma) { 91 DiagnosticMapping Result; 92 Result.Severity = (unsigned)Severity; 93 Result.IsUser = IsUser; 94 Result.IsPragma = IsPragma; 95 Result.HasNoWarningAsError = 0; 96 Result.HasNoErrorAsFatal = 0; 97 return Result; 98 } 99 getSeverity()100 diag::Severity getSeverity() const { return (diag::Severity)Severity; } setSeverity(diag::Severity Value)101 void setSeverity(diag::Severity Value) { Severity = (unsigned)Value; } 102 isUser()103 bool isUser() const { return IsUser; } isPragma()104 bool isPragma() const { return IsPragma; } 105 hasNoWarningAsError()106 bool hasNoWarningAsError() const { return HasNoWarningAsError; } setNoWarningAsError(bool Value)107 void setNoWarningAsError(bool Value) { HasNoWarningAsError = Value; } 108 hasNoErrorAsFatal()109 bool hasNoErrorAsFatal() const { return HasNoErrorAsFatal; } setNoErrorAsFatal(bool Value)110 void setNoErrorAsFatal(bool Value) { HasNoErrorAsFatal = Value; } 111 }; 112 113 /// \brief Used for handling and querying diagnostic IDs. 114 /// 115 /// Can be used and shared by multiple Diagnostics for multiple translation units. 116 class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> { 117 public: 118 /// \brief The level of the diagnostic, after it has been through mapping. 119 enum Level { 120 Ignored, Note, Remark, Warning, Error, Fatal 121 }; 122 123 private: 124 /// \brief Information for uniquing and looking up custom diags. 125 diag::CustomDiagInfo *CustomDiagInfo; 126 127 public: 128 DiagnosticIDs(); 129 ~DiagnosticIDs(); 130 131 /// \brief Return an ID for a diagnostic with the specified format string and 132 /// level. 133 /// 134 /// If this is the first request for this diagnostic, it is registered and 135 /// created, otherwise the existing ID is returned. 136 137 // FIXME: Replace this function with a create-only facilty like 138 // createCustomDiagIDFromFormatString() to enforce safe usage. At the time of 139 // writing, nearly all callers of this function were invalid. 140 unsigned getCustomDiagID(Level L, StringRef FormatString); 141 142 //===--------------------------------------------------------------------===// 143 // Diagnostic classification and reporting interfaces. 144 // 145 146 /// \brief Given a diagnostic ID, return a description of the issue. 147 StringRef getDescription(unsigned DiagID) const; 148 149 /// \brief Return true if the unmapped diagnostic levelof the specified 150 /// diagnostic ID is a Warning or Extension. 151 /// 152 /// This only works on builtin diagnostics, not custom ones, and is not 153 /// legal to call on NOTEs. 154 static bool isBuiltinWarningOrExtension(unsigned DiagID); 155 156 /// \brief Return true if the specified diagnostic is mapped to errors by 157 /// default. 158 static bool isDefaultMappingAsError(unsigned DiagID); 159 160 /// \brief Determine whether the given built-in diagnostic ID is a Note. 161 static bool isBuiltinNote(unsigned DiagID); 162 163 /// \brief Determine whether the given built-in diagnostic ID is for an 164 /// extension of some sort. isBuiltinExtensionDiag(unsigned DiagID)165 static bool isBuiltinExtensionDiag(unsigned DiagID) { 166 bool ignored; 167 return isBuiltinExtensionDiag(DiagID, ignored); 168 } 169 170 /// \brief Determine whether the given built-in diagnostic ID is for an 171 /// extension of some sort, and whether it is enabled by default. 172 /// 173 /// This also returns EnabledByDefault, which is set to indicate whether the 174 /// diagnostic is ignored by default (in which case -pedantic enables it) or 175 /// treated as a warning/error by default. 176 /// 177 static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault); 178 179 180 /// \brief Return the lowest-level warning option that enables the specified 181 /// diagnostic. 182 /// 183 /// If there is no -Wfoo flag that controls the diagnostic, this returns null. 184 static StringRef getWarningOptionForDiag(unsigned DiagID); 185 186 /// \brief Return the category number that a specified \p DiagID belongs to, 187 /// or 0 if no category. 188 static unsigned getCategoryNumberForDiag(unsigned DiagID); 189 190 /// \brief Return the number of diagnostic categories. 191 static unsigned getNumberOfCategories(); 192 193 /// \brief Given a category ID, return the name of the category. 194 static StringRef getCategoryNameFromID(unsigned CategoryID); 195 196 /// \brief Return true if a given diagnostic falls into an ARC diagnostic 197 /// category. 198 static bool isARCDiagnostic(unsigned DiagID); 199 200 /// \brief Enumeration describing how the emission of a diagnostic should 201 /// be treated when it occurs during C++ template argument deduction. 202 enum SFINAEResponse { 203 /// \brief The diagnostic should not be reported, but it should cause 204 /// template argument deduction to fail. 205 /// 206 /// The vast majority of errors that occur during template argument 207 /// deduction fall into this category. 208 SFINAE_SubstitutionFailure, 209 210 /// \brief The diagnostic should be suppressed entirely. 211 /// 212 /// Warnings generally fall into this category. 213 SFINAE_Suppress, 214 215 /// \brief The diagnostic should be reported. 216 /// 217 /// The diagnostic should be reported. Various fatal errors (e.g., 218 /// template instantiation depth exceeded) fall into this category. 219 SFINAE_Report, 220 221 /// \brief The diagnostic is an access-control diagnostic, which will be 222 /// substitution failures in some contexts and reported in others. 223 SFINAE_AccessControl 224 }; 225 226 /// \brief Determines whether the given built-in diagnostic ID is 227 /// for an error that is suppressed if it occurs during C++ template 228 /// argument deduction. 229 /// 230 /// When an error is suppressed due to SFINAE, the template argument 231 /// deduction fails but no diagnostic is emitted. Certain classes of 232 /// errors, such as those errors that involve C++ access control, 233 /// are not SFINAE errors. 234 static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID); 235 236 /// \brief Get the set of all diagnostic IDs in the group with the given name. 237 /// 238 /// \param[out] Diags - On return, the diagnostics in the group. 239 /// \returns \c true if the given group is unknown, \c false otherwise. 240 bool getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group, 241 SmallVectorImpl<diag::kind> &Diags) const; 242 243 /// \brief Get the set of all diagnostic IDs. 244 void getAllDiagnostics(diag::Flavor Flavor, 245 SmallVectorImpl<diag::kind> &Diags) const; 246 247 /// \brief Get the diagnostic option with the closest edit distance to the 248 /// given group name. 249 static StringRef getNearestOption(diag::Flavor Flavor, StringRef Group); 250 251 private: 252 /// \brief Classify the specified diagnostic ID into a Level, consumable by 253 /// the DiagnosticClient. 254 /// 255 /// The classification is based on the way the client configured the 256 /// DiagnosticsEngine object. 257 /// 258 /// \param Loc The source location for which we are interested in finding out 259 /// the diagnostic state. Can be null in order to query the latest state. 260 DiagnosticIDs::Level 261 getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, 262 const DiagnosticsEngine &Diag) const LLVM_READONLY; 263 264 diag::Severity 265 getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, 266 const DiagnosticsEngine &Diag) const LLVM_READONLY; 267 268 /// \brief Used to report a diagnostic that is finally fully formed. 269 /// 270 /// \returns \c true if the diagnostic was emitted, \c false if it was 271 /// suppressed. 272 bool ProcessDiag(DiagnosticsEngine &Diag) const; 273 274 /// \brief Used to emit a diagnostic that is finally fully formed, 275 /// ignoring suppression. 276 void EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const; 277 278 /// \brief Whether the diagnostic may leave the AST in a state where some 279 /// invariants can break. 280 bool isUnrecoverable(unsigned DiagID) const; 281 282 friend class DiagnosticsEngine; 283 }; 284 285 } // end namespace clang 286 287 #endif 288