DiagnosticIDs.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- DiagnosticIDs.h - Diagnostic IDs Handling --------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. ///
  14. /// \file
  15. /// Defines the Diagnostic IDs-related interfaces.
  16. ///
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_CLANG_BASIC_DIAGNOSTICIDS_H
  19. #define LLVM_CLANG_BASIC_DIAGNOSTICIDS_H
  20. #include "clang/Basic/LLVM.h"
  21. #include "llvm/ADT/IntrusiveRefCntPtr.h"
  22. #include "llvm/ADT/StringRef.h"
  23. #include <vector>
  24. namespace clang {
  25. class DiagnosticsEngine;
  26. class SourceLocation;
  27. // Import the diagnostic enums themselves.
  28. namespace diag {
  29. enum class Group;
  30. // Size of each of the diagnostic categories.
  31. enum {
  32. DIAG_SIZE_COMMON = 300,
  33. DIAG_SIZE_DRIVER = 300,
  34. DIAG_SIZE_FRONTEND = 150,
  35. DIAG_SIZE_SERIALIZATION = 120,
  36. DIAG_SIZE_LEX = 400,
  37. DIAG_SIZE_PARSE = 600,
  38. DIAG_SIZE_AST = 250,
  39. DIAG_SIZE_COMMENT = 100,
  40. DIAG_SIZE_CROSSTU = 100,
  41. DIAG_SIZE_SEMA = 4500,
  42. DIAG_SIZE_ANALYSIS = 100,
  43. DIAG_SIZE_REFACTORING = 1000,
  44. };
  45. // Start position for diagnostics.
  46. enum {
  47. DIAG_START_COMMON = 0,
  48. DIAG_START_DRIVER = DIAG_START_COMMON + DIAG_SIZE_COMMON,
  49. DIAG_START_FRONTEND = DIAG_START_DRIVER + DIAG_SIZE_DRIVER,
  50. DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + DIAG_SIZE_FRONTEND,
  51. DIAG_START_LEX = DIAG_START_SERIALIZATION + DIAG_SIZE_SERIALIZATION,
  52. DIAG_START_PARSE = DIAG_START_LEX + DIAG_SIZE_LEX,
  53. DIAG_START_AST = DIAG_START_PARSE + DIAG_SIZE_PARSE,
  54. DIAG_START_COMMENT = DIAG_START_AST + DIAG_SIZE_AST,
  55. DIAG_START_CROSSTU = DIAG_START_COMMENT + DIAG_SIZE_COMMENT,
  56. DIAG_START_SEMA = DIAG_START_CROSSTU + DIAG_SIZE_CROSSTU,
  57. DIAG_START_ANALYSIS = DIAG_START_SEMA + DIAG_SIZE_SEMA,
  58. DIAG_START_REFACTORING = DIAG_START_ANALYSIS + DIAG_SIZE_ANALYSIS,
  59. DIAG_UPPER_LIMIT = DIAG_START_REFACTORING + DIAG_SIZE_REFACTORING
  60. };
  61. class CustomDiagInfo;
  62. /// All of the diagnostics that can be emitted by the frontend.
  63. typedef unsigned kind;
  64. // Get typedefs for common diagnostics.
  65. enum {
  66. #define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, CATEGORY, \
  67. NOWERROR, SHOWINSYSHEADER, SHOWINSYSMACRO, DEFFERABLE) \
  68. ENUM,
  69. #define COMMONSTART
  70. #include "clang/Basic/DiagnosticCommonKinds.inc"
  71. NUM_BUILTIN_COMMON_DIAGNOSTICS
  72. #undef DIAG
  73. };
  74. /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
  75. /// to either Ignore (nothing), Remark (emit a remark), Warning
  76. /// (emit a warning) or Error (emit as an error). It allows clients to
  77. /// map ERRORs to Error or Fatal (stop emitting diagnostics after this one).
  78. enum class Severity {
  79. // NOTE: 0 means "uncomputed".
  80. Ignored = 1, ///< Do not present this diagnostic, ignore it.
  81. Remark = 2, ///< Present this diagnostic as a remark.
  82. Warning = 3, ///< Present this diagnostic as a warning.
  83. Error = 4, ///< Present this diagnostic as an error.
  84. Fatal = 5 ///< Present this diagnostic as a fatal error.
  85. };
  86. /// Flavors of diagnostics we can emit. Used to filter for a particular
  87. /// kind of diagnostic (for instance, for -W/-R flags).
  88. enum class Flavor {
  89. WarningOrError, ///< A diagnostic that indicates a problem or potential
  90. ///< problem. Can be made fatal by -Werror.
  91. Remark ///< A diagnostic that indicates normal progress through
  92. ///< compilation.
  93. };
  94. }
  95. class DiagnosticMapping {
  96. unsigned Severity : 3;
  97. unsigned IsUser : 1;
  98. unsigned IsPragma : 1;
  99. unsigned HasNoWarningAsError : 1;
  100. unsigned HasNoErrorAsFatal : 1;
  101. unsigned WasUpgradedFromWarning : 1;
  102. public:
  103. static DiagnosticMapping Make(diag::Severity Severity, bool IsUser,
  104. bool IsPragma) {
  105. DiagnosticMapping Result;
  106. Result.Severity = (unsigned)Severity;
  107. Result.IsUser = IsUser;
  108. Result.IsPragma = IsPragma;
  109. Result.HasNoWarningAsError = 0;
  110. Result.HasNoErrorAsFatal = 0;
  111. Result.WasUpgradedFromWarning = 0;
  112. return Result;
  113. }
  114. diag::Severity getSeverity() const { return (diag::Severity)Severity; }
  115. void setSeverity(diag::Severity Value) { Severity = (unsigned)Value; }
  116. bool isUser() const { return IsUser; }
  117. bool isPragma() const { return IsPragma; }
  118. bool isErrorOrFatal() const {
  119. return getSeverity() == diag::Severity::Error ||
  120. getSeverity() == diag::Severity::Fatal;
  121. }
  122. bool hasNoWarningAsError() const { return HasNoWarningAsError; }
  123. void setNoWarningAsError(bool Value) { HasNoWarningAsError = Value; }
  124. bool hasNoErrorAsFatal() const { return HasNoErrorAsFatal; }
  125. void setNoErrorAsFatal(bool Value) { HasNoErrorAsFatal = Value; }
  126. /// Whether this mapping attempted to map the diagnostic to a warning, but
  127. /// was overruled because the diagnostic was already mapped to an error or
  128. /// fatal error.
  129. bool wasUpgradedFromWarning() const { return WasUpgradedFromWarning; }
  130. void setUpgradedFromWarning(bool Value) { WasUpgradedFromWarning = Value; }
  131. /// Serialize this mapping as a raw integer.
  132. unsigned serialize() const {
  133. return (IsUser << 7) | (IsPragma << 6) | (HasNoWarningAsError << 5) |
  134. (HasNoErrorAsFatal << 4) | (WasUpgradedFromWarning << 3) | Severity;
  135. }
  136. /// Deserialize a mapping.
  137. static DiagnosticMapping deserialize(unsigned Bits) {
  138. DiagnosticMapping Result;
  139. Result.IsUser = (Bits >> 7) & 1;
  140. Result.IsPragma = (Bits >> 6) & 1;
  141. Result.HasNoWarningAsError = (Bits >> 5) & 1;
  142. Result.HasNoErrorAsFatal = (Bits >> 4) & 1;
  143. Result.WasUpgradedFromWarning = (Bits >> 3) & 1;
  144. Result.Severity = Bits & 0x7;
  145. return Result;
  146. }
  147. };
  148. /// Used for handling and querying diagnostic IDs.
  149. ///
  150. /// Can be used and shared by multiple Diagnostics for multiple translation units.
  151. class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
  152. public:
  153. /// The level of the diagnostic, after it has been through mapping.
  154. enum Level {
  155. Ignored, Note, Remark, Warning, Error, Fatal
  156. };
  157. private:
  158. /// Information for uniquing and looking up custom diags.
  159. std::unique_ptr<diag::CustomDiagInfo> CustomDiagInfo;
  160. public:
  161. DiagnosticIDs();
  162. ~DiagnosticIDs();
  163. /// Return an ID for a diagnostic with the specified format string and
  164. /// level.
  165. ///
  166. /// If this is the first request for this diagnostic, it is registered and
  167. /// created, otherwise the existing ID is returned.
  168. // FIXME: Replace this function with a create-only facilty like
  169. // createCustomDiagIDFromFormatString() to enforce safe usage. At the time of
  170. // writing, nearly all callers of this function were invalid.
  171. unsigned getCustomDiagID(Level L, StringRef FormatString);
  172. //===--------------------------------------------------------------------===//
  173. // Diagnostic classification and reporting interfaces.
  174. //
  175. /// Given a diagnostic ID, return a description of the issue.
  176. StringRef getDescription(unsigned DiagID) const;
  177. /// Return true if the unmapped diagnostic levelof the specified
  178. /// diagnostic ID is a Warning or Extension.
  179. ///
  180. /// This only works on builtin diagnostics, not custom ones, and is not
  181. /// legal to call on NOTEs.
  182. static bool isBuiltinWarningOrExtension(unsigned DiagID);
  183. /// Return true if the specified diagnostic is mapped to errors by
  184. /// default.
  185. static bool isDefaultMappingAsError(unsigned DiagID);
  186. /// Determine whether the given built-in diagnostic ID is a Note.
  187. static bool isBuiltinNote(unsigned DiagID);
  188. /// Determine whether the given built-in diagnostic ID is for an
  189. /// extension of some sort.
  190. static bool isBuiltinExtensionDiag(unsigned DiagID) {
  191. bool ignored;
  192. return isBuiltinExtensionDiag(DiagID, ignored);
  193. }
  194. /// Determine whether the given built-in diagnostic ID is for an
  195. /// extension of some sort, and whether it is enabled by default.
  196. ///
  197. /// This also returns EnabledByDefault, which is set to indicate whether the
  198. /// diagnostic is ignored by default (in which case -pedantic enables it) or
  199. /// treated as a warning/error by default.
  200. ///
  201. static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault);
  202. /// Given a group ID, returns the flag that toggles the group.
  203. /// For example, for Group::DeprecatedDeclarations, returns
  204. /// "deprecated-declarations".
  205. static StringRef getWarningOptionForGroup(diag::Group);
  206. /// Return the lowest-level warning option that enables the specified
  207. /// diagnostic.
  208. ///
  209. /// If there is no -Wfoo flag that controls the diagnostic, this returns null.
  210. static StringRef getWarningOptionForDiag(unsigned DiagID);
  211. /// Return the category number that a specified \p DiagID belongs to,
  212. /// or 0 if no category.
  213. static unsigned getCategoryNumberForDiag(unsigned DiagID);
  214. /// Return the number of diagnostic categories.
  215. static unsigned getNumberOfCategories();
  216. /// Given a category ID, return the name of the category.
  217. static StringRef getCategoryNameFromID(unsigned CategoryID);
  218. /// Return true if a given diagnostic falls into an ARC diagnostic
  219. /// category.
  220. static bool isARCDiagnostic(unsigned DiagID);
  221. /// Enumeration describing how the emission of a diagnostic should
  222. /// be treated when it occurs during C++ template argument deduction.
  223. enum SFINAEResponse {
  224. /// The diagnostic should not be reported, but it should cause
  225. /// template argument deduction to fail.
  226. ///
  227. /// The vast majority of errors that occur during template argument
  228. /// deduction fall into this category.
  229. SFINAE_SubstitutionFailure,
  230. /// The diagnostic should be suppressed entirely.
  231. ///
  232. /// Warnings generally fall into this category.
  233. SFINAE_Suppress,
  234. /// The diagnostic should be reported.
  235. ///
  236. /// The diagnostic should be reported. Various fatal errors (e.g.,
  237. /// template instantiation depth exceeded) fall into this category.
  238. SFINAE_Report,
  239. /// The diagnostic is an access-control diagnostic, which will be
  240. /// substitution failures in some contexts and reported in others.
  241. SFINAE_AccessControl
  242. };
  243. /// Determines whether the given built-in diagnostic ID is
  244. /// for an error that is suppressed if it occurs during C++ template
  245. /// argument deduction.
  246. ///
  247. /// When an error is suppressed due to SFINAE, the template argument
  248. /// deduction fails but no diagnostic is emitted. Certain classes of
  249. /// errors, such as those errors that involve C++ access control,
  250. /// are not SFINAE errors.
  251. static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID);
  252. /// Whether the diagnostic message can be deferred.
  253. ///
  254. /// For single source offloading languages, a diagnostic message occurred
  255. /// in a device host function may be deferred until the function is sure
  256. /// to be emitted.
  257. static bool isDeferrable(unsigned DiagID);
  258. /// Get the string of all diagnostic flags.
  259. ///
  260. /// \returns A list of all diagnostics flags as they would be written in a
  261. /// command line invocation including their `no-` variants. For example:
  262. /// `{"-Wempty-body", "-Wno-empty-body", ...}`
  263. static std::vector<std::string> getDiagnosticFlags();
  264. /// Get the set of all diagnostic IDs in the group with the given name.
  265. ///
  266. /// \param[out] Diags - On return, the diagnostics in the group.
  267. /// \returns \c true if the given group is unknown, \c false otherwise.
  268. bool getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
  269. SmallVectorImpl<diag::kind> &Diags) const;
  270. /// Get the set of all diagnostic IDs.
  271. static void getAllDiagnostics(diag::Flavor Flavor,
  272. std::vector<diag::kind> &Diags);
  273. /// Get the diagnostic option with the closest edit distance to the
  274. /// given group name.
  275. static StringRef getNearestOption(diag::Flavor Flavor, StringRef Group);
  276. private:
  277. /// Classify the specified diagnostic ID into a Level, consumable by
  278. /// the DiagnosticClient.
  279. ///
  280. /// The classification is based on the way the client configured the
  281. /// DiagnosticsEngine object.
  282. ///
  283. /// \param Loc The source location for which we are interested in finding out
  284. /// the diagnostic state. Can be null in order to query the latest state.
  285. DiagnosticIDs::Level
  286. getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
  287. const DiagnosticsEngine &Diag) const LLVM_READONLY;
  288. diag::Severity
  289. getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
  290. const DiagnosticsEngine &Diag) const LLVM_READONLY;
  291. /// Used to report a diagnostic that is finally fully formed.
  292. ///
  293. /// \returns \c true if the diagnostic was emitted, \c false if it was
  294. /// suppressed.
  295. bool ProcessDiag(DiagnosticsEngine &Diag) const;
  296. /// Used to emit a diagnostic that is finally fully formed,
  297. /// ignoring suppression.
  298. void EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const;
  299. /// Whether the diagnostic may leave the AST in a state where some
  300. /// invariants can break.
  301. bool isUnrecoverable(unsigned DiagID) const;
  302. friend class DiagnosticsEngine;
  303. };
  304. } // end namespace clang
  305. #endif
  306. #ifdef __GNUC__
  307. #pragma GCC diagnostic pop
  308. #endif