1218887Sdim//===--- DiagnosticIDs.h - Diagnostic IDs Handling --------------*- C++ -*-===//
2218887Sdim//
3218887Sdim//                     The LLVM Compiler Infrastructure
4218887Sdim//
5218887Sdim// This file is distributed under the University of Illinois Open Source
6218887Sdim// License. See LICENSE.TXT for details.
7218887Sdim//
8218887Sdim//===----------------------------------------------------------------------===//
9239462Sdim///
10239462Sdim/// \file
11239462Sdim/// \brief Defines the Diagnostic IDs-related interfaces.
12239462Sdim///
13218887Sdim//===----------------------------------------------------------------------===//
14218887Sdim
15218887Sdim#ifndef LLVM_CLANG_DIAGNOSTICIDS_H
16218887Sdim#define LLVM_CLANG_DIAGNOSTICIDS_H
17218887Sdim
18249423Sdim#include "clang/Basic/LLVM.h"
19218887Sdim#include "llvm/ADT/IntrusiveRefCntPtr.h"
20218887Sdim#include "llvm/ADT/StringRef.h"
21218887Sdim
22218887Sdimnamespace clang {
23226633Sdim  class DiagnosticsEngine;
24218887Sdim  class SourceLocation;
25218887Sdim
26218887Sdim  // Import the diagnostic enums themselves.
27218887Sdim  namespace diag {
28218887Sdim    // Start position for diagnostics.
29218887Sdim    enum {
30263508Sdim      DIAG_START_COMMON        =                                 0,
31263508Sdim      DIAG_START_DRIVER        = DIAG_START_COMMON          +  300,
32234353Sdim      DIAG_START_FRONTEND      = DIAG_START_DRIVER          +  100,
33234353Sdim      DIAG_START_SERIALIZATION = DIAG_START_FRONTEND        +  100,
34234353Sdim      DIAG_START_LEX           = DIAG_START_SERIALIZATION   +  120,
35234353Sdim      DIAG_START_PARSE         = DIAG_START_LEX             +  300,
36234353Sdim      DIAG_START_AST           = DIAG_START_PARSE           +  400,
37239462Sdim      DIAG_START_COMMENT       = DIAG_START_AST             +  100,
38239462Sdim      DIAG_START_SEMA          = DIAG_START_COMMENT         +  100,
39234353Sdim      DIAG_START_ANALYSIS      = DIAG_START_SEMA            + 3000,
40234353Sdim      DIAG_UPPER_LIMIT         = DIAG_START_ANALYSIS        +  100
41218887Sdim    };
42218887Sdim
43218887Sdim    class CustomDiagInfo;
44218887Sdim
45239462Sdim    /// \brief All of the diagnostics that can be emitted by the frontend.
46218887Sdim    typedef unsigned kind;
47218887Sdim
48218887Sdim    // Get typedefs for common diagnostics.
49218887Sdim    enum {
50221345Sdim#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\
51263508Sdim             SFINAE,CATEGORY,NOWERROR,SHOWINSYSHEADER) ENUM,
52263508Sdim#define COMMONSTART
53218887Sdim#include "clang/Basic/DiagnosticCommonKinds.inc"
54218887Sdim      NUM_BUILTIN_COMMON_DIAGNOSTICS
55218887Sdim#undef DIAG
56218887Sdim    };
57218887Sdim
58218887Sdim    /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
59218887Sdim    /// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR
60218887Sdim    /// (emit as an error).  It allows clients to map errors to
61218887Sdim    /// MAP_ERROR/MAP_DEFAULT or MAP_FATAL (stop emitting diagnostics after this
62218887Sdim    /// one).
63218887Sdim    enum Mapping {
64218887Sdim      // NOTE: 0 means "uncomputed".
65239462Sdim      MAP_IGNORE  = 1,     ///< Map this diagnostic to nothing, ignore it.
66239462Sdim      MAP_WARNING = 2,     ///< Map this diagnostic to a warning.
67239462Sdim      MAP_ERROR   = 3,     ///< Map this diagnostic to an error.
68239462Sdim      MAP_FATAL   = 4      ///< Map this diagnostic to a fatal error.
69218887Sdim    };
70218887Sdim  }
71218887Sdim
72226633Sdimclass DiagnosticMappingInfo {
73226633Sdim  unsigned Mapping : 3;
74226633Sdim  unsigned IsUser : 1;
75226633Sdim  unsigned IsPragma : 1;
76226633Sdim  unsigned HasShowInSystemHeader : 1;
77226633Sdim  unsigned HasNoWarningAsError : 1;
78226633Sdim  unsigned HasNoErrorAsFatal : 1;
79226633Sdim
80226633Sdimpublic:
81226633Sdim  static DiagnosticMappingInfo Make(diag::Mapping Mapping, bool IsUser,
82226633Sdim                                    bool IsPragma) {
83226633Sdim    DiagnosticMappingInfo Result;
84226633Sdim    Result.Mapping = Mapping;
85226633Sdim    Result.IsUser = IsUser;
86226633Sdim    Result.IsPragma = IsPragma;
87226633Sdim    Result.HasShowInSystemHeader = 0;
88226633Sdim    Result.HasNoWarningAsError = 0;
89226633Sdim    Result.HasNoErrorAsFatal = 0;
90226633Sdim    return Result;
91226633Sdim  }
92226633Sdim
93226633Sdim  diag::Mapping getMapping() const { return diag::Mapping(Mapping); }
94226633Sdim  void setMapping(diag::Mapping Value) { Mapping = Value; }
95226633Sdim
96226633Sdim  bool isUser() const { return IsUser; }
97226633Sdim  bool isPragma() const { return IsPragma; }
98226633Sdim
99226633Sdim  bool hasShowInSystemHeader() const { return HasShowInSystemHeader; }
100226633Sdim  void setShowInSystemHeader(bool Value) { HasShowInSystemHeader = Value; }
101226633Sdim
102226633Sdim  bool hasNoWarningAsError() const { return HasNoWarningAsError; }
103226633Sdim  void setNoWarningAsError(bool Value) { HasNoWarningAsError = Value; }
104226633Sdim
105226633Sdim  bool hasNoErrorAsFatal() const { return HasNoErrorAsFatal; }
106226633Sdim  void setNoErrorAsFatal(bool Value) { HasNoErrorAsFatal = Value; }
107226633Sdim};
108226633Sdim
109263508Sdim/// \brief Used for handling and querying diagnostic IDs.
110263508Sdim///
111263508Sdim/// Can be used and shared by multiple Diagnostics for multiple translation units.
112234353Sdimclass DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
113218887Sdimpublic:
114263508Sdim  /// \brief The level of the diagnostic, after it has been through mapping.
115218887Sdim  enum Level {
116218887Sdim    Ignored, Note, Warning, Error, Fatal
117218887Sdim  };
118218887Sdim
119218887Sdimprivate:
120239462Sdim  /// \brief Information for uniquing and looking up custom diags.
121218887Sdim  diag::CustomDiagInfo *CustomDiagInfo;
122218887Sdim
123218887Sdimpublic:
124218887Sdim  DiagnosticIDs();
125218887Sdim  ~DiagnosticIDs();
126218887Sdim
127239462Sdim  /// \brief Return an ID for a diagnostic with the specified message and level.
128239462Sdim  ///
129249423Sdim  /// If this is the first request for this diagnostic, it is registered and
130239462Sdim  /// created, otherwise the existing ID is returned.
131226633Sdim  unsigned getCustomDiagID(Level L, StringRef Message);
132218887Sdim
133218887Sdim  //===--------------------------------------------------------------------===//
134218887Sdim  // Diagnostic classification and reporting interfaces.
135218887Sdim  //
136218887Sdim
137239462Sdim  /// \brief Given a diagnostic ID, return a description of the issue.
138226633Sdim  StringRef getDescription(unsigned DiagID) const;
139218887Sdim
140239462Sdim  /// \brief Return true if the unmapped diagnostic levelof the specified
141239462Sdim  /// diagnostic ID is a Warning or Extension.
142239462Sdim  ///
143239462Sdim  /// This only works on builtin diagnostics, not custom ones, and is not
144239462Sdim  /// legal to call on NOTEs.
145218887Sdim  static bool isBuiltinWarningOrExtension(unsigned DiagID);
146218887Sdim
147226633Sdim  /// \brief Return true if the specified diagnostic is mapped to errors by
148226633Sdim  /// default.
149226633Sdim  static bool isDefaultMappingAsError(unsigned DiagID);
150226633Sdim
151239462Sdim  /// \brief Determine whether the given built-in diagnostic ID is a Note.
152218887Sdim  static bool isBuiltinNote(unsigned DiagID);
153218887Sdim
154239462Sdim  /// \brief Determine whether the given built-in diagnostic ID is for an
155239462Sdim  /// extension of some sort.
156218887Sdim  static bool isBuiltinExtensionDiag(unsigned DiagID) {
157218887Sdim    bool ignored;
158218887Sdim    return isBuiltinExtensionDiag(DiagID, ignored);
159218887Sdim  }
160218887Sdim
161239462Sdim  /// \brief Determine whether the given built-in diagnostic ID is for an
162239462Sdim  /// extension of some sort, and whether it is enabled by default.
163218887Sdim  ///
164239462Sdim  /// This also returns EnabledByDefault, which is set to indicate whether the
165239462Sdim  /// diagnostic is ignored by default (in which case -pedantic enables it) or
166239462Sdim  /// treated as a warning/error by default.
167239462Sdim  ///
168218887Sdim  static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault);
169218887Sdim
170218887Sdim
171239462Sdim  /// \brief Return the lowest-level warning option that enables the specified
172239462Sdim  /// diagnostic.
173239462Sdim  ///
174239462Sdim  /// If there is no -Wfoo flag that controls the diagnostic, this returns null.
175226633Sdim  static StringRef getWarningOptionForDiag(unsigned DiagID);
176223017Sdim
177239462Sdim  /// \brief Return the category number that a specified \p DiagID belongs to,
178239462Sdim  /// or 0 if no category.
179218887Sdim  static unsigned getCategoryNumberForDiag(unsigned DiagID);
180218887Sdim
181239462Sdim  /// \brief Return the number of diagnostic categories.
182223017Sdim  static unsigned getNumberOfCategories();
183223017Sdim
184239462Sdim  /// \brief Given a category ID, return the name of the category.
185226633Sdim  static StringRef getCategoryNameFromID(unsigned CategoryID);
186218887Sdim
187239462Sdim  /// \brief Return true if a given diagnostic falls into an ARC diagnostic
188239462Sdim  /// category.
189234353Sdim  static bool isARCDiagnostic(unsigned DiagID);
190234353Sdim
191239462Sdim  /// \brief Enumeration describing how the emission of a diagnostic should
192218887Sdim  /// be treated when it occurs during C++ template argument deduction.
193218887Sdim  enum SFINAEResponse {
194218887Sdim    /// \brief The diagnostic should not be reported, but it should cause
195218887Sdim    /// template argument deduction to fail.
196218887Sdim    ///
197218887Sdim    /// The vast majority of errors that occur during template argument
198218887Sdim    /// deduction fall into this category.
199218887Sdim    SFINAE_SubstitutionFailure,
200218887Sdim
201218887Sdim    /// \brief The diagnostic should be suppressed entirely.
202218887Sdim    ///
203218887Sdim    /// Warnings generally fall into this category.
204218887Sdim    SFINAE_Suppress,
205218887Sdim
206218887Sdim    /// \brief The diagnostic should be reported.
207218887Sdim    ///
208218887Sdim    /// The diagnostic should be reported. Various fatal errors (e.g.,
209218887Sdim    /// template instantiation depth exceeded) fall into this category.
210218887Sdim    SFINAE_Report,
211218887Sdim
212218887Sdim    /// \brief The diagnostic is an access-control diagnostic, which will be
213218887Sdim    /// substitution failures in some contexts and reported in others.
214218887Sdim    SFINAE_AccessControl
215218887Sdim  };
216218887Sdim
217218887Sdim  /// \brief Determines whether the given built-in diagnostic ID is
218218887Sdim  /// for an error that is suppressed if it occurs during C++ template
219218887Sdim  /// argument deduction.
220218887Sdim  ///
221218887Sdim  /// When an error is suppressed due to SFINAE, the template argument
222218887Sdim  /// deduction fails but no diagnostic is emitted. Certain classes of
223218887Sdim  /// errors, such as those errors that involve C++ access control,
224218887Sdim  /// are not SFINAE errors.
225218887Sdim  static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID);
226218887Sdim
227226633Sdim  /// \brief Get the set of all diagnostic IDs in the group with the given name.
228226633Sdim  ///
229263508Sdim  /// \param[out] Diags - On return, the diagnostics in the group.
230263508Sdim  /// \returns \c true if the given group is unknown, \c false otherwise.
231226633Sdim  bool getDiagnosticsInGroup(StringRef Group,
232249423Sdim                             SmallVectorImpl<diag::kind> &Diags) const;
233226633Sdim
234234353Sdim  /// \brief Get the set of all diagnostic IDs.
235249423Sdim  void getAllDiagnostics(SmallVectorImpl<diag::kind> &Diags) const;
236234353Sdim
237234353Sdim  /// \brief Get the warning option with the closest edit distance to the given
238234353Sdim  /// group name.
239234353Sdim  static StringRef getNearestWarningOption(StringRef Group);
240234353Sdim
241218887Sdimprivate:
242263508Sdim  /// \brief Classify the specified diagnostic ID into a Level, consumable by
243218887Sdim  /// the DiagnosticClient.
244263508Sdim  ///
245263508Sdim  /// The classification is based on the way the client configured the
246263508Sdim  /// DiagnosticsEngine object.
247218887Sdim  ///
248263508Sdim  /// \param Loc The source location for which we are interested in finding out
249263508Sdim  /// the diagnostic state. Can be null in order to query the latest state.
250218887Sdim  DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
251226633Sdim                                          const DiagnosticsEngine &Diag) const;
252218887Sdim
253239462Sdim  /// \brief An internal implementation helper used when \p DiagClass is
254239462Sdim  /// already known.
255218887Sdim  DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID,
256218887Sdim                                          unsigned DiagClass,
257218887Sdim                                          SourceLocation Loc,
258226633Sdim                                          const DiagnosticsEngine &Diag) const;
259218887Sdim
260239462Sdim  /// \brief Used to report a diagnostic that is finally fully formed.
261218887Sdim  ///
262239462Sdim  /// \returns \c true if the diagnostic was emitted, \c false if it was
263218887Sdim  /// suppressed.
264226633Sdim  bool ProcessDiag(DiagnosticsEngine &Diag) const;
265218887Sdim
266239462Sdim  /// \brief Used to emit a diagnostic that is finally fully formed,
267239462Sdim  /// ignoring suppression.
268239462Sdim  void EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const;
269239462Sdim
270224145Sdim  /// \brief Whether the diagnostic may leave the AST in a state where some
271224145Sdim  /// invariants can break.
272224145Sdim  bool isUnrecoverable(unsigned DiagID) const;
273224145Sdim
274226633Sdim  friend class DiagnosticsEngine;
275218887Sdim};
276218887Sdim
277218887Sdim}  // end namespace clang
278218887Sdim
279218887Sdim#endif
280