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