Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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