//===- Diagnostic.h - C Language Family Diagnostic Handling -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// \file
/// Defines the Diagnostic-related interfaces.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_BASIC_DIAGNOSTIC_H
#define LLVM_CLANG_BASIC_DIAGNOSTIC_H

#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
#include <cassert>
#include <cstdint>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>

namespace llvm {
class Error;
}

namespace clang {

class DeclContext;
class DiagnosticBuilder;
class DiagnosticConsumer;
class IdentifierInfo;
class LangOptions;
class Preprocessor;
class SourceManager;
class StoredDiagnostic;

namespace tok {

enum TokenKind : unsigned short;

} // namespace tok

/// Annotates a diagnostic with some code that should be
/// inserted, removed, or replaced to fix the problem.
///
/// This kind of hint should be used when we are certain that the
/// introduction, removal, or modification of a particular (small!)
/// amount of code will correct a compilation error. The compiler
/// should also provide full recovery from such errors, such that
/// suppressing the diagnostic output can still result in successful
/// compilation.
class FixItHint {
public:
  /// Code that should be replaced to correct the error. Empty for an
  /// insertion hint.
  CharSourceRange RemoveRange;

  /// Code in the specific range that should be inserted in the insertion
  /// location.
  CharSourceRange InsertFromRange;

  /// The actual code to insert at the insertion location, as a
  /// string.
  std::string CodeToInsert;

  bool BeforePreviousInsertions = false;

  /// Empty code modification hint, indicating that no code
  /// modification is known.
  FixItHint() = default;

  bool isNull() const {
    return !RemoveRange.isValid();
  }

  /// Create a code modification hint that inserts the given
  /// code string at a specific location.
  static FixItHint CreateInsertion(SourceLocation InsertionLoc,
                                   StringRef Code,
                                   bool BeforePreviousInsertions = false) {
    FixItHint Hint;
    Hint.RemoveRange =
      CharSourceRange::getCharRange(InsertionLoc, InsertionLoc);
    Hint.CodeToInsert = std::string(Code);
    Hint.BeforePreviousInsertions = BeforePreviousInsertions;
    return Hint;
  }

  /// Create a code modification hint that inserts the given
  /// code from \p FromRange at a specific location.
  static FixItHint CreateInsertionFromRange(SourceLocation InsertionLoc,
                                            CharSourceRange FromRange,
                                        bool BeforePreviousInsertions = false) {
    FixItHint Hint;
    Hint.RemoveRange =
      CharSourceRange::getCharRange(InsertionLoc, InsertionLoc);
    Hint.InsertFromRange = FromRange;
    Hint.BeforePreviousInsertions = BeforePreviousInsertions;
    return Hint;
  }

  /// Create a code modification hint that removes the given
  /// source range.
  static FixItHint CreateRemoval(CharSourceRange RemoveRange) {
    FixItHint Hint;
    Hint.RemoveRange = RemoveRange;
    return Hint;
  }
  static FixItHint CreateRemoval(SourceRange RemoveRange) {
    return CreateRemoval(CharSourceRange::getTokenRange(RemoveRange));
  }

  /// Create a code modification hint that replaces the given
  /// source range with the given code string.
  static FixItHint CreateReplacement(CharSourceRange RemoveRange,
                                     StringRef Code) {
    FixItHint Hint;
    Hint.RemoveRange = RemoveRange;
    Hint.CodeToInsert = std::string(Code);
    return Hint;
  }

  static FixItHint CreateReplacement(SourceRange RemoveRange,
                                     StringRef Code) {
    return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code);
  }
};

struct DiagnosticStorage {
  enum {
    /// The maximum number of arguments we can hold. We
    /// currently only support up to 10 arguments (%0-%9).
    ///
    /// A single diagnostic with more than that almost certainly has to
    /// be simplified anyway.
    MaxArguments = 10
  };

  /// The number of entries in Arguments.
  unsigned char NumDiagArgs = 0;

  /// Specifies for each argument whether it is in DiagArgumentsStr
  /// or in DiagArguments.
  unsigned char DiagArgumentsKind[MaxArguments];

  /// The values for the various substitution positions.
  ///
  /// This is used when the argument is not an std::string. The specific value
  /// is mangled into an intptr_t and the interpretation depends on exactly
  /// what sort of argument kind it is.
  intptr_t DiagArgumentsVal[MaxArguments];

  /// The values for the various substitution positions that have
  /// string arguments.
  std::string DiagArgumentsStr[MaxArguments];

  /// The list of ranges added to this diagnostic.
  SmallVector<CharSourceRange, 8> DiagRanges;

  /// If valid, provides a hint with some code to insert, remove, or
  /// modify at a particular position.
  SmallVector<FixItHint, 6> FixItHints;

  DiagnosticStorage() = default;
};

/// Concrete class used by the front-end to report problems and issues.
///
/// This massages the diagnostics (e.g. handling things like "report warnings
/// as errors" and passes them off to the DiagnosticConsumer for reporting to
/// the user. DiagnosticsEngine is tied to one translation unit and one
/// SourceManager.
class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
public:
  /// The level of the diagnostic, after it has been through mapping.
  enum Level {
    Ignored = DiagnosticIDs::Ignored,
    Note = DiagnosticIDs::Note,
    Remark = DiagnosticIDs::Remark,
    Warning = DiagnosticIDs::Warning,
    Error = DiagnosticIDs::Error,
    Fatal = DiagnosticIDs::Fatal
  };

  enum ArgumentKind {
    /// std::string
    ak_std_string,

    /// const char *
    ak_c_string,

    /// int
    ak_sint,

    /// unsigned
    ak_uint,

    /// enum TokenKind : unsigned
    ak_tokenkind,

    /// IdentifierInfo
    ak_identifierinfo,

    /// address space
    ak_addrspace,

    /// Qualifiers
    ak_qual,

    /// QualType
    ak_qualtype,

    /// DeclarationName
    ak_declarationname,

    /// NamedDecl *
    ak_nameddecl,

    /// NestedNameSpecifier *
    ak_nestednamespec,

    /// DeclContext *
    ak_declcontext,

    /// pair<QualType, QualType>
    ak_qualtype_pair,

    /// Attr *
    ak_attr
  };

  /// Represents on argument value, which is a union discriminated
  /// by ArgumentKind, with a value.
  using ArgumentValue = std::pair<ArgumentKind, intptr_t>;

private:
  // Used by __extension__
  unsigned char AllExtensionsSilenced = 0;

  // Treat fatal errors like errors.
  bool FatalsAsError = false;

  // Suppress all diagnostics.
  bool SuppressAllDiagnostics = false;

  // Elide common types of templates.
  bool ElideType = true;

  // Print a tree when comparing templates.
  bool PrintTemplateTree = false;

  // Color printing is enabled.
  bool ShowColors = false;

  // Which overload candidates to show.
  OverloadsShown ShowOverloads = Ovl_All;

  // With Ovl_Best, the number of overload candidates to show when we encounter
  // an error.
  //
  // The value here is the number of candidates to show in the first nontrivial
  // error.  Future errors may show a different number of candidates.
  unsigned NumOverloadsToShow = 32;

  // Cap of # errors emitted, 0 -> no limit.
  unsigned ErrorLimit = 0;

  // Cap on depth of template backtrace stack, 0 -> no limit.
  unsigned TemplateBacktraceLimit = 0;

  // Cap on depth of constexpr evaluation backtrace stack, 0 -> no limit.
  unsigned ConstexprBacktraceLimit = 0;

  IntrusiveRefCntPtr<DiagnosticIDs> Diags;
  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
  DiagnosticConsumer *Client = nullptr;
  std::unique_ptr<DiagnosticConsumer> Owner;
  SourceManager *SourceMgr = nullptr;

  /// Mapping information for diagnostics.
  ///
  /// Mapping info is packed into four bits per diagnostic.  The low three
  /// bits are the mapping (an instance of diag::Severity), or zero if unset.
  /// The high bit is set when the mapping was established as a user mapping.
  /// If the high bit is clear, then the low bits are set to the default
  /// value, and should be mapped with -pedantic, -Werror, etc.
  ///
  /// A new DiagState is created and kept around when diagnostic pragmas modify
  /// the state so that we know what is the diagnostic state at any given
  /// source location.
  class DiagState {
    llvm::DenseMap<unsigned, DiagnosticMapping> DiagMap;

  public:
    // "Global" configuration state that can actually vary between modules.

    // Ignore all warnings: -w
    unsigned IgnoreAllWarnings : 1;

    // Enable all warnings.
    unsigned EnableAllWarnings : 1;

    // Treat warnings like errors.
    unsigned WarningsAsErrors : 1;

    // Treat errors like fatal errors.
    unsigned ErrorsAsFatal : 1;

    // Suppress warnings in system headers.
    unsigned SuppressSystemWarnings : 1;

    // Map extensions to warnings or errors?
    diag::Severity ExtBehavior = diag::Severity::Ignored;

    DiagState()
        : IgnoreAllWarnings(false), EnableAllWarnings(false),
          WarningsAsErrors(false), ErrorsAsFatal(false),
          SuppressSystemWarnings(false) {}

    using iterator = llvm::DenseMap<unsigned, DiagnosticMapping>::iterator;
    using const_iterator =
        llvm::DenseMap<unsigned, DiagnosticMapping>::const_iterator;

    void setMapping(diag::kind Diag, DiagnosticMapping Info) {
      DiagMap[Diag] = Info;
    }

    DiagnosticMapping lookupMapping(diag::kind Diag) const {
      return DiagMap.lookup(Diag);
    }

    DiagnosticMapping &getOrAddMapping(diag::kind Diag);

    const_iterator begin() const { return DiagMap.begin(); }
    const_iterator end() const { return DiagMap.end(); }
  };

  /// Keeps and automatically disposes all DiagStates that we create.
  std::list<DiagState> DiagStates;

  /// A mapping from files to the diagnostic states for those files. Lazily
  /// built on demand for files in which the diagnostic state has not changed.
  class DiagStateMap {
  public:
    /// Add an initial diagnostic state.
    void appendFirst(DiagState *State);

    /// Add a new latest state point.
    void append(SourceManager &SrcMgr, SourceLocation Loc, DiagState *State);

    /// Look up the diagnostic state at a given source location.
    DiagState *lookup(SourceManager &SrcMgr, SourceLocation Loc) const;

    /// Determine whether this map is empty.
    bool empty() const { return Files.empty(); }

    /// Clear out this map.
    void clear() {
      Files.clear();
      FirstDiagState = CurDiagState = nullptr;
      CurDiagStateLoc = SourceLocation();
    }

    /// Produce a debugging dump of the diagnostic state.
    LLVM_DUMP_METHOD void dump(SourceManager &SrcMgr,
                               StringRef DiagName = StringRef()) const;

    /// Grab the most-recently-added state point.
    DiagState *getCurDiagState() const { return CurDiagState; }

    /// Get the location at which a diagnostic state was last added.
    SourceLocation getCurDiagStateLoc() const { return CurDiagStateLoc; }

  private:
    friend class ASTReader;
    friend class ASTWriter;

    /// Represents a point in source where the diagnostic state was
    /// modified because of a pragma.
    ///
    /// 'Loc' can be null if the point represents the diagnostic state
    /// modifications done through the command-line.
    struct DiagStatePoint {
      DiagState *State;
      unsigned Offset;

      DiagStatePoint(DiagState *State, unsigned Offset)
          : State(State), Offset(Offset) {}
    };

    /// Description of the diagnostic states and state transitions for a
    /// particular FileID.
    struct File {
      /// The diagnostic state for the parent file. This is strictly redundant,
      /// as looking up the DecomposedIncludedLoc for the FileID in the Files
      /// map would give us this, but we cache it here for performance.
      File *Parent = nullptr;

      /// The offset of this file within its parent.
      unsigned ParentOffset = 0;

      /// Whether this file has any local (not imported from an AST file)
      /// diagnostic state transitions.
      bool HasLocalTransitions = false;

      /// The points within the file where the state changes. There will always
      /// be at least one of these (the state on entry to the file).
      llvm::SmallVector<DiagStatePoint, 4> StateTransitions;

      DiagState *lookup(unsigned Offset) const;
    };

    /// The diagnostic states for each file.
    mutable std::map<FileID, File> Files;

    /// The initial diagnostic state.
    DiagState *FirstDiagState;

    /// The current diagnostic state.
    DiagState *CurDiagState;

    /// The location at which the current diagnostic state was established.
    SourceLocation CurDiagStateLoc;

    /// Get the diagnostic state information for a file.
    File *getFile(SourceManager &SrcMgr, FileID ID) const;
  };

  DiagStateMap DiagStatesByLoc;

  /// Keeps the DiagState that was active during each diagnostic 'push'
  /// so we can get back at it when we 'pop'.
  std::vector<DiagState *> DiagStateOnPushStack;

  DiagState *GetCurDiagState() const {
    return DiagStatesByLoc.getCurDiagState();
  }

  void PushDiagStatePoint(DiagState *State, SourceLocation L);

  /// Finds the DiagStatePoint that contains the diagnostic state of
  /// the given source location.
  DiagState *GetDiagStateForLoc(SourceLocation Loc) const {
    return SourceMgr ? DiagStatesByLoc.lookup(*SourceMgr, Loc)
                     : DiagStatesByLoc.getCurDiagState();
  }

  /// Sticky flag set to \c true when an error is emitted.
  bool ErrorOccurred;

  /// Sticky flag set to \c true when an "uncompilable error" occurs.
  /// I.e. an error that was not upgraded from a warning by -Werror.
  bool UncompilableErrorOccurred;

  /// Sticky flag set to \c true when a fatal error is emitted.
  bool FatalErrorOccurred;

  /// Indicates that an unrecoverable error has occurred.
  bool UnrecoverableErrorOccurred;

  /// Counts for DiagnosticErrorTrap to check whether an error occurred
  /// during a parsing section, e.g. during parsing a function.
  unsigned TrapNumErrorsOccurred;
  unsigned TrapNumUnrecoverableErrorsOccurred;

  /// The level of the last diagnostic emitted.
  ///
  /// This is used to emit continuation diagnostics with the same level as the
  /// diagnostic that they follow.
  DiagnosticIDs::Level LastDiagLevel;

  /// Number of warnings reported
  unsigned NumWarnings;

  /// Number of errors reported
  unsigned NumErrors;

  /// A function pointer that converts an opaque diagnostic
  /// argument to a strings.
  ///
  /// This takes the modifiers and argument that was present in the diagnostic.
  ///
  /// The PrevArgs array indicates the previous arguments formatted for this
  /// diagnostic.  Implementations of this function can use this information to
  /// avoid redundancy across arguments.
  ///
  /// This is a hack to avoid a layering violation between libbasic and libsema.
  using ArgToStringFnTy = void (*)(
      ArgumentKind Kind, intptr_t Val,
      StringRef Modifier, StringRef Argument,
      ArrayRef<ArgumentValue> PrevArgs,
      SmallVectorImpl<char> &Output,
      void *Cookie,
      ArrayRef<intptr_t> QualTypeVals);

  void *ArgToStringCookie = nullptr;
  ArgToStringFnTy ArgToStringFn;

  /// ID of the "delayed" diagnostic, which is a (typically
  /// fatal) diagnostic that had to be delayed because it was found
  /// while emitting another diagnostic.
  unsigned DelayedDiagID;

  /// First string argument for the delayed diagnostic.
  std::string DelayedDiagArg1;

  /// Second string argument for the delayed diagnostic.
  std::string DelayedDiagArg2;

  /// Third string argument for the delayed diagnostic.
  std::string DelayedDiagArg3;

  /// Optional flag value.
  ///
  /// Some flags accept values, for instance: -Wframe-larger-than=<value> and
  /// -Rpass=<value>. The content of this string is emitted after the flag name
  /// and '='.
  std::string FlagValue;

public:
  explicit DiagnosticsEngine(IntrusiveRefCntPtr<DiagnosticIDs> Diags,
                             IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
                             DiagnosticConsumer *client = nullptr,
                             bool ShouldOwnClient = true);
  DiagnosticsEngine(const DiagnosticsEngine &) = delete;
  DiagnosticsEngine &operator=(const DiagnosticsEngine &) = delete;
  ~DiagnosticsEngine();

  LLVM_DUMP_METHOD void dump() const;
  LLVM_DUMP_METHOD void dump(StringRef DiagName) const;

  const IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const {
    return Diags;
  }

  /// Retrieve the diagnostic options.
  DiagnosticOptions &getDiagnosticOptions() const { return *DiagOpts; }

  using diag_mapping_range = llvm::iterator_range<DiagState::const_iterator>;

  /// Get the current set of diagnostic mappings.
  diag_mapping_range getDiagnosticMappings() const {
    const DiagState &DS = *GetCurDiagState();
    return diag_mapping_range(DS.begin(), DS.end());
  }

  DiagnosticConsumer *getClient() { return Client; }
  const DiagnosticConsumer *getClient() const { return Client; }

  /// Determine whether this \c DiagnosticsEngine object own its client.
  bool ownsClient() const { return Owner != nullptr; }

  /// Return the current diagnostic client along with ownership of that
  /// client.
  std::unique_ptr<DiagnosticConsumer> takeClient() { return std::move(Owner); }

  bool hasSourceManager() const { return SourceMgr != nullptr; }

  SourceManager &getSourceManager() const {
    assert(SourceMgr && "SourceManager not set!");
    return *SourceMgr;
  }

  void setSourceManager(SourceManager *SrcMgr) {
    assert(DiagStatesByLoc.empty() &&
           "Leftover diag state from a different SourceManager.");
    SourceMgr = SrcMgr;
  }

  //===--------------------------------------------------------------------===//
  //  DiagnosticsEngine characterization methods, used by a client to customize
  //  how diagnostics are emitted.
  //

  /// Copies the current DiagMappings and pushes the new copy
  /// onto the top of the stack.
  void pushMappings(SourceLocation Loc);

  /// Pops the current DiagMappings off the top of the stack,
  /// causing the new top of the stack to be the active mappings.
  ///
  /// \returns \c true if the pop happens, \c false if there is only one
  /// DiagMapping on the stack.
  bool popMappings(SourceLocation Loc);

  /// Set the diagnostic client associated with this diagnostic object.
  ///
  /// \param ShouldOwnClient true if the diagnostic object should take
  /// ownership of \c client.
  void setClient(DiagnosticConsumer *client, bool ShouldOwnClient = true);

  /// Specify a limit for the number of errors we should
  /// emit before giving up.
  ///
  /// Zero disables the limit.
  void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; }

  /// Specify the maximum number of template instantiation
  /// notes to emit along with a given diagnostic.
  void setTemplateBacktraceLimit(unsigned Limit) {
    TemplateBacktraceLimit = Limit;
  }

  /// Retrieve the maximum number of template instantiation
  /// notes to emit along with a given diagnostic.
  unsigned getTemplateBacktraceLimit() const {
    return TemplateBacktraceLimit;
  }

  /// Specify the maximum number of constexpr evaluation
  /// notes to emit along with a given diagnostic.
  void setConstexprBacktraceLimit(unsigned Limit) {
    ConstexprBacktraceLimit = Limit;
  }

  /// Retrieve the maximum number of constexpr evaluation
  /// notes to emit along with a given diagnostic.
  unsigned getConstexprBacktraceLimit() const {
    return ConstexprBacktraceLimit;
  }

  /// When set to true, any unmapped warnings are ignored.
  ///
  /// If this and WarningsAsErrors are both set, then this one wins.
  void setIgnoreAllWarnings(bool Val) {
    GetCurDiagState()->IgnoreAllWarnings = Val;
  }
  bool getIgnoreAllWarnings() const {
    return GetCurDiagState()->IgnoreAllWarnings;
  }

  /// When set to true, any unmapped ignored warnings are no longer
  /// ignored.
  ///
  /// If this and IgnoreAllWarnings are both set, then that one wins.
  void setEnableAllWarnings(bool Val) {
    GetCurDiagState()->EnableAllWarnings = Val;
  }
  bool getEnableAllWarnings() const {
    return GetCurDiagState()->EnableAllWarnings;
  }

  /// When set to true, any warnings reported are issued as errors.
  void setWarningsAsErrors(bool Val) {
    GetCurDiagState()->WarningsAsErrors = Val;
  }
  bool getWarningsAsErrors() const {
    return GetCurDiagState()->WarningsAsErrors;
  }

  /// When set to true, any error reported is made a fatal error.
  void setErrorsAsFatal(bool Val) { GetCurDiagState()->ErrorsAsFatal = Val; }
  bool getErrorsAsFatal() const { return GetCurDiagState()->ErrorsAsFatal; }

  /// \brief When set to true, any fatal error reported is made an error.
  ///
  /// This setting takes precedence over the setErrorsAsFatal setting above.
  void setFatalsAsError(bool Val) { FatalsAsError = Val; }
  bool getFatalsAsError() const { return FatalsAsError; }

  /// When set to true mask warnings that come from system headers.
  void setSuppressSystemWarnings(bool Val) {
    GetCurDiagState()->SuppressSystemWarnings = Val;
  }
  bool getSuppressSystemWarnings() const {
    return GetCurDiagState()->SuppressSystemWarnings;
  }

  /// Suppress all diagnostics, to silence the front end when we
  /// know that we don't want any more diagnostics to be passed along to the
  /// client
  void setSuppressAllDiagnostics(bool Val) { SuppressAllDiagnostics = Val; }
  bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; }

  /// Set type eliding, to skip outputting same types occurring in
  /// template types.
  void setElideType(bool Val) { ElideType = Val; }
  bool getElideType() { return ElideType; }

  /// Set tree printing, to outputting the template difference in a
  /// tree format.
  void setPrintTemplateTree(bool Val) { PrintTemplateTree = Val; }
  bool getPrintTemplateTree() { return PrintTemplateTree; }

  /// Set color printing, so the type diffing will inject color markers
  /// into the output.
  void setShowColors(bool Val) { ShowColors = Val; }
  bool getShowColors() { return ShowColors; }

  /// Specify which overload candidates to show when overload resolution
  /// fails.
  ///
  /// By default, we show all candidates.
  void setShowOverloads(OverloadsShown Val) {
    ShowOverloads = Val;
  }
  OverloadsShown getShowOverloads() const { return ShowOverloads; }

  /// When a call or operator fails, print out up to this many candidate
  /// overloads as suggestions.
  ///
  /// With Ovl_Best, we set a high limit for the first nontrivial overload set
  /// we print, and a lower limit for later sets.  This way the user has a
  /// chance of diagnosing at least one callsite in their program without
  /// having to recompile with -fshow-overloads=all.
  unsigned getNumOverloadCandidatesToShow() const {
    switch (getShowOverloads()) {
    case Ovl_All:
      // INT_MAX rather than UINT_MAX so that we don't have to think about the
      // effect of implicit conversions on this value. In practice we'll never
      // hit 2^31 candidates anyway.
      return std::numeric_limits<int>::max();
    case Ovl_Best:
      return NumOverloadsToShow;
    }
    llvm_unreachable("invalid OverloadsShown kind");
  }

  /// Call this after showing N overload candidates.  This influences the value
  /// returned by later calls to getNumOverloadCandidatesToShow().
  void overloadCandidatesShown(unsigned N) {
    // Current heuristic: Start out with a large value for NumOverloadsToShow,
    // and then once we print one nontrivially-large overload set, decrease it
    // for future calls.
    if (N > 4) {
      NumOverloadsToShow = 4;
    }
  }

  /// Pretend that the last diagnostic issued was ignored, so any
  /// subsequent notes will be suppressed, or restore a prior ignoring
  /// state after ignoring some diagnostics and their notes, possibly in
  /// the middle of another diagnostic.
  ///
  /// This can be used by clients who suppress diagnostics themselves.
  void setLastDiagnosticIgnored(bool Ignored) {
    if (LastDiagLevel == DiagnosticIDs::Fatal)
      FatalErrorOccurred = true;
    LastDiagLevel = Ignored ? DiagnosticIDs::Ignored : DiagnosticIDs::Warning;
  }

  /// Determine whether the previous diagnostic was ignored. This can
  /// be used by clients that want to determine whether notes attached to a
  /// diagnostic will be suppressed.
  bool isLastDiagnosticIgnored() const {
    return LastDiagLevel == DiagnosticIDs::Ignored;
  }

  /// Controls whether otherwise-unmapped extension diagnostics are
  /// mapped onto ignore/warning/error.
  ///
  /// This corresponds to the GCC -pedantic and -pedantic-errors option.
  void setExtensionHandlingBehavior(diag::Severity H) {
    GetCurDiagState()->ExtBehavior = H;
  }
  diag::Severity getExtensionHandlingBehavior() const {
    return GetCurDiagState()->ExtBehavior;
  }

  /// Counter bumped when an __extension__  block is/ encountered.
  ///
  /// When non-zero, all extension diagnostics are entirely silenced, no
  /// matter how they are mapped.
  void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; }
  void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; }
  bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; }

  /// This allows the client to specify that certain warnings are
  /// ignored.
  ///
  /// Notes can never be mapped, errors can only be mapped to fatal, and
  /// WARNINGs and EXTENSIONs can be mapped arbitrarily.
  ///
  /// \param Loc The source location that this change of diagnostic state should
  /// take affect. It can be null if we are setting the latest state.
  void setSeverity(diag::kind Diag, diag::Severity Map, SourceLocation Loc);

  /// Change an entire diagnostic group (e.g. "unknown-pragmas") to
  /// have the specified mapping.
  ///
  /// \returns true (and ignores the request) if "Group" was unknown, false
  /// otherwise.
  ///
  /// \param Flavor The flavor of group to affect. -Rfoo does not affect the
  /// state of the -Wfoo group and vice versa.
  ///
  /// \param Loc The source location that this change of diagnostic state should
  /// take affect. It can be null if we are setting the state from command-line.
  bool setSeverityForGroup(diag::Flavor Flavor, StringRef Group,
                           diag::Severity Map,
                           SourceLocation Loc = SourceLocation());

  /// Set the warning-as-error flag for the given diagnostic group.
  ///
  /// This function always only operates on the current diagnostic state.
  ///
  /// \returns True if the given group is unknown, false otherwise.
  bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled);

  /// Set the error-as-fatal flag for the given diagnostic group.
  ///
  /// This function always only operates on the current diagnostic state.
  ///
  /// \returns True if the given group is unknown, false otherwise.
  bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled);

  /// Add the specified mapping to all diagnostics of the specified
  /// flavor.
  ///
  /// Mainly to be used by -Wno-everything to disable all warnings but allow
  /// subsequent -W options to enable specific warnings.
  void setSeverityForAll(diag::Flavor Flavor, diag::Severity Map,
                         SourceLocation Loc = SourceLocation());

  bool hasErrorOccurred() const { return ErrorOccurred; }

  /// Errors that actually prevent compilation, not those that are
  /// upgraded from a warning by -Werror.
  bool hasUncompilableErrorOccurred() const {
    return UncompilableErrorOccurred;
  }
  bool hasFatalErrorOccurred() const { return FatalErrorOccurred; }

  /// Determine whether any kind of unrecoverable error has occurred.
  bool hasUnrecoverableErrorOccurred() const {
    return FatalErrorOccurred || UnrecoverableErrorOccurred;
  }

  unsigned getNumErrors() const { return NumErrors; }
  unsigned getNumWarnings() const { return NumWarnings; }

  void setNumWarnings(unsigned NumWarnings) {
    this->NumWarnings = NumWarnings;
  }

  /// Return an ID for a diagnostic with the specified format string and
  /// level.
  ///
  /// If this is the first request for this diagnostic, it is registered and
  /// created, otherwise the existing ID is returned.
  ///
  /// \param FormatString A fixed diagnostic format string that will be hashed
  /// and mapped to a unique DiagID.
  template <unsigned N>
  unsigned getCustomDiagID(Level L, const char (&FormatString)[N]) {
    return Diags->getCustomDiagID((DiagnosticIDs::Level)L,
                                  StringRef(FormatString, N - 1));
  }

  /// Converts a diagnostic argument (as an intptr_t) into the string
  /// that represents it.
  void ConvertArgToString(ArgumentKind Kind, intptr_t Val,
                          StringRef Modifier, StringRef Argument,
                          ArrayRef<ArgumentValue> PrevArgs,
                          SmallVectorImpl<char> &Output,
                          ArrayRef<intptr_t> QualTypeVals) const {
    ArgToStringFn(Kind, Val, Modifier, Argument, PrevArgs, Output,
                  ArgToStringCookie, QualTypeVals);
  }

  void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) {
    ArgToStringFn = Fn;
    ArgToStringCookie = Cookie;
  }

  /// Note that the prior diagnostic was emitted by some other
  /// \c DiagnosticsEngine, and we may be attaching a note to that diagnostic.
  void notePriorDiagnosticFrom(const DiagnosticsEngine &Other) {
    LastDiagLevel = Other.LastDiagLevel;
  }

  /// Reset the state of the diagnostic object to its initial
  /// configuration.
  void Reset();

  //===--------------------------------------------------------------------===//
  // DiagnosticsEngine classification and reporting interfaces.
  //

  /// Determine whether the diagnostic is known to be ignored.
  ///
  /// This can be used to opportunistically avoid expensive checks when it's
  /// known for certain that the diagnostic has been suppressed at the
  /// specified location \p Loc.
  ///
  /// \param Loc The source location we are interested in finding out the
  /// diagnostic state. Can be null in order to query the latest state.
  bool isIgnored(unsigned DiagID, SourceLocation Loc) const {
    return Diags->getDiagnosticSeverity(DiagID, Loc, *this) ==
           diag::Severity::Ignored;
  }

  /// Based on the way the client configured the DiagnosticsEngine
  /// object, classify the specified diagnostic ID into a Level, consumable by
  /// the DiagnosticConsumer.
  ///
  /// To preserve invariant assumptions, this function should not be used to
  /// influence parse or semantic analysis actions. Instead consider using
  /// \c isIgnored().
  ///
  /// \param Loc The source location we are interested in finding out the
  /// diagnostic state. Can be null in order to query the latest state.
  Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const {
    return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this);
  }

  /// Issue the message to the client.
  ///
  /// This actually returns an instance of DiagnosticBuilder which emits the
  /// diagnostics (through @c ProcessDiag) when it is destroyed.
  ///
  /// \param DiagID A member of the @c diag::kind enum.
  /// \param Loc Represents the source location associated with the diagnostic,
  /// which can be an invalid location if no position information is available.
  inline DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID);
  inline DiagnosticBuilder Report(unsigned DiagID);

  void Report(const StoredDiagnostic &storedDiag);

  /// Determine whethere there is already a diagnostic in flight.
  bool isDiagnosticInFlight() const {
    return CurDiagID != std::numeric_limits<unsigned>::max();
  }

  /// Set the "delayed" diagnostic that will be emitted once
  /// the current diagnostic completes.
  ///
  ///  If a diagnostic is already in-flight but the front end must
  ///  report a problem (e.g., with an inconsistent file system
  ///  state), this routine sets a "delayed" diagnostic that will be
  ///  emitted after the current diagnostic completes. This should
  ///  only be used for fatal errors detected at inconvenient
  ///  times. If emitting a delayed diagnostic causes a second delayed
  ///  diagnostic to be introduced, that second delayed diagnostic
  ///  will be ignored.
  ///
  /// \param DiagID The ID of the diagnostic being delayed.
  ///
  /// \param Arg1 A string argument that will be provided to the
  /// diagnostic. A copy of this string will be stored in the
  /// DiagnosticsEngine object itself.
  ///
  /// \param Arg2 A string argument that will be provided to the
  /// diagnostic. A copy of this string will be stored in the
  /// DiagnosticsEngine object itself.
  ///
  /// \param Arg3 A string argument that will be provided to the
  /// diagnostic. A copy of this string will be stored in the
  /// DiagnosticsEngine object itself.
  void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "",
                            StringRef Arg2 = "", StringRef Arg3 = "");

  /// Clear out the current diagnostic.
  void Clear() { CurDiagID = std::numeric_limits<unsigned>::max(); }

  /// Return the value associated with this diagnostic flag.
  StringRef getFlagValue() const { return FlagValue; }

private:
  // This is private state used by DiagnosticBuilder.  We put it here instead of
  // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight
  // object.  This implementation choice means that we can only have one
  // diagnostic "in flight" at a time, but this seems to be a reasonable
  // tradeoff to keep these objects small.  Assertions verify that only one
  // diagnostic is in flight at a time.
  friend class Diagnostic;
  friend class DiagnosticBuilder;
  friend class DiagnosticErrorTrap;
  friend class DiagnosticIDs;
  friend class PartialDiagnostic;

  /// Report the delayed diagnostic.
  void ReportDelayed();

  /// The location of the current diagnostic that is in flight.
  SourceLocation CurDiagLoc;

  /// The ID of the current diagnostic that is in flight.
  ///
  /// This is set to std::numeric_limits<unsigned>::max() when there is no
  /// diagnostic in flight.
  unsigned CurDiagID;

  enum {
    /// The maximum number of arguments we can hold.
    ///
    /// We currently only support up to 10 arguments (%0-%9).  A single
    /// diagnostic with more than that almost certainly has to be simplified
    /// anyway.
    MaxArguments = DiagnosticStorage::MaxArguments,
  };

  DiagnosticStorage DiagStorage;

  DiagnosticMapping makeUserMapping(diag::Severity Map, SourceLocation L) {
    bool isPragma = L.isValid();
    DiagnosticMapping Mapping =
        DiagnosticMapping::Make(Map, /*IsUser=*/true, isPragma);

    // If this is a pragma mapping, then set the diagnostic mapping flags so
    // that we override command line options.
    if (isPragma) {
      Mapping.setNoWarningAsError(true);
      Mapping.setNoErrorAsFatal(true);
    }

    return Mapping;
  }

  /// Used to report a diagnostic that is finally fully formed.
  ///
  /// \returns true if the diagnostic was emitted, false if it was suppressed.
  bool ProcessDiag() {
    return Diags->ProcessDiag(*this);
  }

  /// @name Diagnostic Emission
  /// @{
protected:
  friend class ASTReader;
  friend class ASTWriter;

  // Sema requires access to the following functions because the current design
  // of SFINAE requires it to use its own SemaDiagnosticBuilder, which needs to
  // access us directly to ensure we minimize the emitted code for the common
  // Sema::Diag() patterns.
  friend class Sema;

  /// Emit the current diagnostic and clear the diagnostic state.
  ///
  /// \param Force Emit the diagnostic regardless of suppression settings.
  bool EmitCurrentDiagnostic(bool Force = false);

  unsigned getCurrentDiagID() const { return CurDiagID; }

  SourceLocation getCurrentDiagLoc() const { return CurDiagLoc; }

  /// @}
};

/// RAII class that determines when any errors have occurred
/// between the time the instance was created and the time it was
/// queried.
///
/// Note that you almost certainly do not want to use this. It's usually
/// meaningless to ask whether a particular scope triggered an error message,
/// because error messages outside that scope can mark things invalid (or cause
/// us to reach an error limit), which can suppress errors within that scope.
class DiagnosticErrorTrap {
  DiagnosticsEngine &Diag;
  unsigned NumErrors;
  unsigned NumUnrecoverableErrors;

public:
  explicit DiagnosticErrorTrap(DiagnosticsEngine &Diag)
      : Diag(Diag) { reset(); }

  /// Determine whether any errors have occurred since this
  /// object instance was created.
  bool hasErrorOccurred() const {
    return Diag.TrapNumErrorsOccurred > NumErrors;
  }

  /// Determine whether any unrecoverable errors have occurred since this
  /// object instance was created.
  bool hasUnrecoverableErrorOccurred() const {
    return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors;
  }

  /// Set to initial state of "no errors occurred".
  void reset() {
    NumErrors = Diag.TrapNumErrorsOccurred;
    NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred;
  }
};

/// The streaming interface shared between DiagnosticBuilder and
/// PartialDiagnostic. This class is not intended to be constructed directly
/// but only as base class of DiagnosticBuilder and PartialDiagnostic builder.
///
/// Any new type of argument accepted by DiagnosticBuilder and PartialDiagnostic
/// should be implemented as a '<<' operator of StreamingDiagnostic, e.g.
///
/// const StreamingDiagnostic&
/// operator<<(const StreamingDiagnostic&, NewArgType);
///
class StreamingDiagnostic {
public:
  /// An allocator for DiagnosticStorage objects, which uses a small cache to
  /// objects, used to reduce malloc()/free() traffic for partial diagnostics.
  class DiagStorageAllocator {
    static const unsigned NumCached = 16;
    DiagnosticStorage Cached[NumCached];
    DiagnosticStorage *FreeList[NumCached];
    unsigned NumFreeListEntries;

  public:
    DiagStorageAllocator();
    ~DiagStorageAllocator();

    /// Allocate new storage.
    DiagnosticStorage *Allocate() {
      if (NumFreeListEntries == 0)
        return new DiagnosticStorage;

      DiagnosticStorage *Result = FreeList[--NumFreeListEntries];
      Result->NumDiagArgs = 0;
      Result->DiagRanges.clear();
      Result->FixItHints.clear();
      return Result;
    }

    /// Free the given storage object.
    void Deallocate(DiagnosticStorage *S) {
      if (S >= Cached && S <= Cached + NumCached) {
        FreeList[NumFreeListEntries++] = S;
        return;
      }

      delete S;
    }
  };

protected:
  mutable DiagnosticStorage *DiagStorage = nullptr;

  /// Allocator used to allocate storage for this diagnostic.
  DiagStorageAllocator *Allocator = nullptr;

public:
  /// Retrieve storage for this particular diagnostic.
  DiagnosticStorage *getStorage() const {
    if (DiagStorage)
      return DiagStorage;

    assert(Allocator);
    DiagStorage = Allocator->Allocate();
    return DiagStorage;
  }

  void freeStorage() {
    if (!DiagStorage)
      return;

    // The hot path for PartialDiagnostic is when we just used it to wrap an ID
    // (typically so we have the flexibility of passing a more complex
    // diagnostic into the callee, but that does not commonly occur).
    //
    // Split this out into a slow function for silly compilers (*cough*) which
    // can't do decent partial inlining.
    freeStorageSlow();
  }

  void freeStorageSlow() {
    if (!Allocator)
      return;
    Allocator->Deallocate(DiagStorage);
    DiagStorage = nullptr;
  }

  void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const {
    if (!DiagStorage)
      DiagStorage = getStorage();

    assert(DiagStorage->NumDiagArgs < DiagnosticStorage::MaxArguments &&
           "Too many arguments to diagnostic!");
    DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] = Kind;
    DiagStorage->DiagArgumentsVal[DiagStorage->NumDiagArgs++] = V;
  }

  void AddString(StringRef V) const {
    if (!DiagStorage)
      DiagStorage = getStorage();

    assert(DiagStorage->NumDiagArgs < DiagnosticStorage::MaxArguments &&
           "Too many arguments to diagnostic!");
    DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] =
        DiagnosticsEngine::ak_std_string;
    DiagStorage->DiagArgumentsStr[DiagStorage->NumDiagArgs++] = std::string(V);
  }

  void AddSourceRange(const CharSourceRange &R) const {
    if (!DiagStorage)
      DiagStorage = getStorage();

    DiagStorage->DiagRanges.push_back(R);
  }

  void AddFixItHint(const FixItHint &Hint) const {
    if (Hint.isNull())
      return;

    if (!DiagStorage)
      DiagStorage = getStorage();

    DiagStorage->FixItHints.push_back(Hint);
  }

  /// Conversion of StreamingDiagnostic to bool always returns \c true.
  ///
  /// This allows is to be used in boolean error contexts (where \c true is
  /// used to indicate that an error has occurred), like:
  /// \code
  /// return Diag(...);
  /// \endcode
  operator bool() const { return true; }

protected:
  StreamingDiagnostic() = default;

  /// Construct with an external storage not owned by itself. The allocator
  /// is a null pointer in this case.
  explicit StreamingDiagnostic(DiagnosticStorage *Storage)
      : DiagStorage(Storage) {}

  /// Construct with a storage allocator which will manage the storage. The
  /// allocator is not a null pointer in this case.
  explicit StreamingDiagnostic(DiagStorageAllocator &Alloc)
      : Allocator(&Alloc) {}

  StreamingDiagnostic(const StreamingDiagnostic &Diag) = default;
  StreamingDiagnostic(StreamingDiagnostic &&Diag) = default;

  ~StreamingDiagnostic() { freeStorage(); }
};

//===----------------------------------------------------------------------===//
// DiagnosticBuilder
//===----------------------------------------------------------------------===//

/// A little helper class used to produce diagnostics.
///
/// This is constructed by the DiagnosticsEngine::Report method, and
/// allows insertion of extra information (arguments and source ranges) into
/// the currently "in flight" diagnostic.  When the temporary for the builder
/// is destroyed, the diagnostic is issued.
///
/// Note that many of these will be created as temporary objects (many call
/// sites), so we want them to be small and we never want their address taken.
/// This ensures that compilers with somewhat reasonable optimizers will promote
/// the common fields to registers, eliminating increments of the NumArgs field,
/// for example.
class DiagnosticBuilder : public StreamingDiagnostic {
  friend class DiagnosticsEngine;
  friend class PartialDiagnostic;

  mutable DiagnosticsEngine *DiagObj = nullptr;

  /// Status variable indicating if this diagnostic is still active.
  ///
  // NOTE: This field is redundant with DiagObj (IsActive iff (DiagObj == 0)),
  // but LLVM is not currently smart enough to eliminate the null check that
  // Emit() would end up with if we used that as our status variable.
  mutable bool IsActive = false;

  /// Flag indicating that this diagnostic is being emitted via a
  /// call to ForceEmit.
  mutable bool IsForceEmit = false;

  DiagnosticBuilder() = default;

  explicit DiagnosticBuilder(DiagnosticsEngine *diagObj)
      : StreamingDiagnostic(&diagObj->DiagStorage), DiagObj(diagObj),
        IsActive(true) {
    assert(diagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!");
    assert(DiagStorage &&
           "DiagnosticBuilder requires a valid DiagnosticStorage!");
    DiagStorage->NumDiagArgs = 0;
    DiagStorage->DiagRanges.clear();
    DiagStorage->FixItHints.clear();
  }

protected:
  /// Clear out the current diagnostic.
  void Clear() const {
    DiagObj = nullptr;
    IsActive = false;
    IsForceEmit = false;
  }

  /// Determine whether this diagnostic is still active.
  bool isActive() const { return IsActive; }

  /// Force the diagnostic builder to emit the diagnostic now.
  ///
  /// Once this function has been called, the DiagnosticBuilder object
  /// should not be used again before it is destroyed.
  ///
  /// \returns true if a diagnostic was emitted, false if the
  /// diagnostic was suppressed.
  bool Emit() {
    // If this diagnostic is inactive, then its soul was stolen by the copy ctor
    // (or by a subclass, as in SemaDiagnosticBuilder).
    if (!isActive()) return false;

    // Process the diagnostic.
    bool Result = DiagObj->EmitCurrentDiagnostic(IsForceEmit);

    // This diagnostic is dead.
    Clear();

    return Result;
  }

public:
  /// Copy constructor.  When copied, this "takes" the diagnostic info from the
  /// input and neuters it.
  DiagnosticBuilder(const DiagnosticBuilder &D) : StreamingDiagnostic() {
    DiagObj = D.DiagObj;
    DiagStorage = D.DiagStorage;
    IsActive = D.IsActive;
    IsForceEmit = D.IsForceEmit;
    D.Clear();
  }

  template <typename T> const DiagnosticBuilder &operator<<(const T &V) const {
    assert(isActive() && "Clients must not add to cleared diagnostic!");
    const StreamingDiagnostic &DB = *this;
    DB << V;
    return *this;
  }

  // It is necessary to limit this to rvalue reference to avoid calling this
  // function with a bitfield lvalue argument since non-const reference to
  // bitfield is not allowed.
  template <typename T, typename = typename std::enable_if<
                            !std::is_lvalue_reference<T>::value>::type>
  const DiagnosticBuilder &operator<<(T &&V) const {
    assert(isActive() && "Clients must not add to cleared diagnostic!");
    const StreamingDiagnostic &DB = *this;
    DB << std::move(V);
    return *this;
  }

  DiagnosticBuilder &operator=(const DiagnosticBuilder &) = delete;

  /// Emits the diagnostic.
  ~DiagnosticBuilder() { Emit(); }

  /// Forces the diagnostic to be emitted.
  const DiagnosticBuilder &setForceEmit() const {
    IsForceEmit = true;
    return *this;
  }

  void addFlagValue(StringRef V) const { DiagObj->FlagValue = std::string(V); }
};

struct AddFlagValue {
  StringRef Val;

  explicit AddFlagValue(StringRef V) : Val(V) {}
};

/// Register a value for the flag in the current diagnostic. This
/// value will be shown as the suffix "=value" after the flag name. It is
/// useful in cases where the diagnostic flag accepts values (e.g.,
/// -Rpass or -Wframe-larger-than).
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
                                           const AddFlagValue V) {
  DB.addFlagValue(V.Val);
  return DB;
}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             StringRef S) {
  DB.AddString(S);
  return DB;
}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             const char *Str) {
  DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str),
                  DiagnosticsEngine::ak_c_string);
  return DB;
}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             int I) {
  DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
  return DB;
}

// We use enable_if here to prevent that this overload is selected for
// pointers or other arguments that are implicitly convertible to bool.
template <typename T>
inline std::enable_if_t<std::is_same<T, bool>::value,
                        const StreamingDiagnostic &>
operator<<(const StreamingDiagnostic &DB, T I) {
  DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
  return DB;
}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             unsigned I) {
  DB.AddTaggedVal(I, DiagnosticsEngine::ak_uint);
  return DB;
}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             tok::TokenKind I) {
  DB.AddTaggedVal(static_cast<unsigned>(I), DiagnosticsEngine::ak_tokenkind);
  return DB;
}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             const IdentifierInfo *II) {
  DB.AddTaggedVal(reinterpret_cast<intptr_t>(II),
                  DiagnosticsEngine::ak_identifierinfo);
  return DB;
}

// Adds a DeclContext to the diagnostic. The enable_if template magic is here
// so that we only match those arguments that are (statically) DeclContexts;
// other arguments that derive from DeclContext (e.g., RecordDecls) will not
// match.
template <typename T>
inline std::enable_if_t<
    std::is_same<std::remove_const_t<T>, DeclContext>::value,
    const StreamingDiagnostic &>
operator<<(const StreamingDiagnostic &DB, T *DC) {
  DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC),
                  DiagnosticsEngine::ak_declcontext);
  return DB;
}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             SourceRange R) {
  DB.AddSourceRange(CharSourceRange::getTokenRange(R));
  return DB;
}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             ArrayRef<SourceRange> Ranges) {
  for (SourceRange R : Ranges)
    DB.AddSourceRange(CharSourceRange::getTokenRange(R));
  return DB;
}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             const CharSourceRange &R) {
  DB.AddSourceRange(R);
  return DB;
}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             const FixItHint &Hint) {
  DB.AddFixItHint(Hint);
  return DB;
}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             ArrayRef<FixItHint> Hints) {
  for (const FixItHint &Hint : Hints)
    DB.AddFixItHint(Hint);
  return DB;
}

inline const StreamingDiagnostic &
operator<<(const StreamingDiagnostic &DB,
           const llvm::Optional<SourceRange> &Opt) {
  if (Opt)
    DB << *Opt;
  return DB;
}

inline const StreamingDiagnostic &
operator<<(const StreamingDiagnostic &DB,
           const llvm::Optional<CharSourceRange> &Opt) {
  if (Opt)
    DB << *Opt;
  return DB;
}

inline const StreamingDiagnostic &
operator<<(const StreamingDiagnostic &DB,
           const llvm::Optional<FixItHint> &Opt) {
  if (Opt)
    DB << *Opt;
  return DB;
}

/// A nullability kind paired with a bit indicating whether it used a
/// context-sensitive keyword.
using DiagNullabilityKind = std::pair<NullabilityKind, bool>;

const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                      DiagNullabilityKind nullability);

inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc,
                                                   unsigned DiagID) {
  assert(CurDiagID == std::numeric_limits<unsigned>::max() &&
         "Multiple diagnostics in flight at once!");
  CurDiagLoc = Loc;
  CurDiagID = DiagID;
  FlagValue.clear();
  return DiagnosticBuilder(this);
}

const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                      llvm::Error &&E);

inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) {
  return Report(SourceLocation(), DiagID);
}

//===----------------------------------------------------------------------===//
// Diagnostic
//===----------------------------------------------------------------------===//

/// A little helper class (which is basically a smart pointer that forwards
/// info from DiagnosticsEngine) that allows clients to enquire about the
/// currently in-flight diagnostic.
class Diagnostic {
  const DiagnosticsEngine *DiagObj;
  StringRef StoredDiagMessage;

public:
  explicit Diagnostic(const DiagnosticsEngine *DO) : DiagObj(DO) {}
  Diagnostic(const DiagnosticsEngine *DO, StringRef storedDiagMessage)
      : DiagObj(DO), StoredDiagMessage(storedDiagMessage) {}

  const DiagnosticsEngine *getDiags() const { return DiagObj; }
  unsigned getID() const { return DiagObj->CurDiagID; }
  const SourceLocation &getLocation() const { return DiagObj->CurDiagLoc; }
  bool hasSourceManager() const { return DiagObj->hasSourceManager(); }
  SourceManager &getSourceManager() const { return DiagObj->getSourceManager();}

  unsigned getNumArgs() const { return DiagObj->DiagStorage.NumDiagArgs; }

  /// Return the kind of the specified index.
  ///
  /// Based on the kind of argument, the accessors below can be used to get
  /// the value.
  ///
  /// \pre Idx < getNumArgs()
  DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const {
    assert(Idx < getNumArgs() && "Argument index out of range!");
    return (DiagnosticsEngine::ArgumentKind)
        DiagObj->DiagStorage.DiagArgumentsKind[Idx];
  }

  /// Return the provided argument string specified by \p Idx.
  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_std_string
  const std::string &getArgStdStr(unsigned Idx) const {
    assert(getArgKind(Idx) == DiagnosticsEngine::ak_std_string &&
           "invalid argument accessor!");
    return DiagObj->DiagStorage.DiagArgumentsStr[Idx];
  }

  /// Return the specified C string argument.
  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_c_string
  const char *getArgCStr(unsigned Idx) const {
    assert(getArgKind(Idx) == DiagnosticsEngine::ak_c_string &&
           "invalid argument accessor!");
    return reinterpret_cast<const char *>(
        DiagObj->DiagStorage.DiagArgumentsVal[Idx]);
  }

  /// Return the specified signed integer argument.
  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_sint
  int getArgSInt(unsigned Idx) const {
    assert(getArgKind(Idx) == DiagnosticsEngine::ak_sint &&
           "invalid argument accessor!");
    return (int)DiagObj->DiagStorage.DiagArgumentsVal[Idx];
  }

  /// Return the specified unsigned integer argument.
  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_uint
  unsigned getArgUInt(unsigned Idx) const {
    assert(getArgKind(Idx) == DiagnosticsEngine::ak_uint &&
           "invalid argument accessor!");
    return (unsigned)DiagObj->DiagStorage.DiagArgumentsVal[Idx];
  }

  /// Return the specified IdentifierInfo argument.
  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo
  const IdentifierInfo *getArgIdentifier(unsigned Idx) const {
    assert(getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo &&
           "invalid argument accessor!");
    return reinterpret_cast<IdentifierInfo *>(
        DiagObj->DiagStorage.DiagArgumentsVal[Idx]);
  }

  /// Return the specified non-string argument in an opaque form.
  /// \pre getArgKind(Idx) != DiagnosticsEngine::ak_std_string
  intptr_t getRawArg(unsigned Idx) const {
    assert(getArgKind(Idx) != DiagnosticsEngine::ak_std_string &&
           "invalid argument accessor!");
    return DiagObj->DiagStorage.DiagArgumentsVal[Idx];
  }

  /// Return the number of source ranges associated with this diagnostic.
  unsigned getNumRanges() const {
    return DiagObj->DiagStorage.DiagRanges.size();
  }

  /// \pre Idx < getNumRanges()
  const CharSourceRange &getRange(unsigned Idx) const {
    assert(Idx < getNumRanges() && "Invalid diagnostic range index!");
    return DiagObj->DiagStorage.DiagRanges[Idx];
  }

  /// Return an array reference for this diagnostic's ranges.
  ArrayRef<CharSourceRange> getRanges() const {
    return DiagObj->DiagStorage.DiagRanges;
  }

  unsigned getNumFixItHints() const {
    return DiagObj->DiagStorage.FixItHints.size();
  }

  const FixItHint &getFixItHint(unsigned Idx) const {
    assert(Idx < getNumFixItHints() && "Invalid index!");
    return DiagObj->DiagStorage.FixItHints[Idx];
  }

  ArrayRef<FixItHint> getFixItHints() const {
    return DiagObj->DiagStorage.FixItHints;
  }

  /// Format this diagnostic into a string, substituting the
  /// formal arguments into the %0 slots.
  ///
  /// The result is appended onto the \p OutStr array.
  void FormatDiagnostic(SmallVectorImpl<char> &OutStr) const;

  /// Format the given format-string into the output buffer using the
  /// arguments stored in this diagnostic.
  void FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
                        SmallVectorImpl<char> &OutStr) const;
};

/**
 * Represents a diagnostic in a form that can be retained until its
 * corresponding source manager is destroyed.
 */
class StoredDiagnostic {
  unsigned ID;
  DiagnosticsEngine::Level Level;
  FullSourceLoc Loc;
  std::string Message;
  std::vector<CharSourceRange> Ranges;
  std::vector<FixItHint> FixIts;

public:
  StoredDiagnostic() = default;
  StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info);
  StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
                   StringRef Message);
  StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
                   StringRef Message, FullSourceLoc Loc,
                   ArrayRef<CharSourceRange> Ranges,
                   ArrayRef<FixItHint> Fixits);

  /// Evaluates true when this object stores a diagnostic.
  explicit operator bool() const { return !Message.empty(); }

  unsigned getID() const { return ID; }
  DiagnosticsEngine::Level getLevel() const { return Level; }
  const FullSourceLoc &getLocation() const { return Loc; }
  StringRef getMessage() const { return Message; }

  void setLocation(FullSourceLoc Loc) { this->Loc = Loc; }

  using range_iterator = std::vector<CharSourceRange>::const_iterator;

  range_iterator range_begin() const { return Ranges.begin(); }
  range_iterator range_end() const { return Ranges.end(); }
  unsigned range_size() const { return Ranges.size(); }

  ArrayRef<CharSourceRange> getRanges() const {
    return llvm::makeArrayRef(Ranges);
  }

  using fixit_iterator = std::vector<FixItHint>::const_iterator;

  fixit_iterator fixit_begin() const { return FixIts.begin(); }
  fixit_iterator fixit_end() const { return FixIts.end(); }
  unsigned fixit_size() const { return FixIts.size(); }

  ArrayRef<FixItHint> getFixIts() const {
    return llvm::makeArrayRef(FixIts);
  }
};

/// Abstract interface, implemented by clients of the front-end, which
/// formats and prints fully processed diagnostics.
class DiagnosticConsumer {
protected:
  unsigned NumWarnings = 0;       ///< Number of warnings reported
  unsigned NumErrors = 0;         ///< Number of errors reported

public:
  DiagnosticConsumer() = default;
  virtual ~DiagnosticConsumer();

  unsigned getNumErrors() const { return NumErrors; }
  unsigned getNumWarnings() const { return NumWarnings; }
  virtual void clear() { NumWarnings = NumErrors = 0; }

  /// Callback to inform the diagnostic client that processing
  /// of a source file is beginning.
  ///
  /// Note that diagnostics may be emitted outside the processing of a source
  /// file, for example during the parsing of command line options. However,
  /// diagnostics with source range information are required to only be emitted
  /// in between BeginSourceFile() and EndSourceFile().
  ///
  /// \param LangOpts The language options for the source file being processed.
  /// \param PP The preprocessor object being used for the source; this is
  /// optional, e.g., it may not be present when processing AST source files.
  virtual void BeginSourceFile(const LangOptions &LangOpts,
                               const Preprocessor *PP = nullptr) {}

  /// Callback to inform the diagnostic client that processing
  /// of a source file has ended.
  ///
  /// The diagnostic client should assume that any objects made available via
  /// BeginSourceFile() are inaccessible.
  virtual void EndSourceFile() {}

  /// Callback to inform the diagnostic client that processing of all
  /// source files has ended.
  virtual void finish() {}

  /// Indicates whether the diagnostics handled by this
  /// DiagnosticConsumer should be included in the number of diagnostics
  /// reported by DiagnosticsEngine.
  ///
  /// The default implementation returns true.
  virtual bool IncludeInDiagnosticCounts() const;

  /// Handle this diagnostic, reporting it to the user or
  /// capturing it to a log as needed.
  ///
  /// The default implementation just keeps track of the total number of
  /// warnings and errors.
  virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                                const Diagnostic &Info);
};

/// A diagnostic client that ignores all diagnostics.
class IgnoringDiagConsumer : public DiagnosticConsumer {
  virtual void anchor();

  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                        const Diagnostic &Info) override {
    // Just ignore it.
  }
};

/// Diagnostic consumer that forwards diagnostics along to an
/// existing, already-initialized diagnostic consumer.
///
class ForwardingDiagnosticConsumer : public DiagnosticConsumer {
  DiagnosticConsumer &Target;

public:
  ForwardingDiagnosticConsumer(DiagnosticConsumer &Target) : Target(Target) {}
  ~ForwardingDiagnosticConsumer() override;

  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                        const Diagnostic &Info) override;
  void clear() override;

  bool IncludeInDiagnosticCounts() const override;
};

// Struct used for sending info about how a type should be printed.
struct TemplateDiffTypes {
  intptr_t FromType;
  intptr_t ToType;
  unsigned PrintTree : 1;
  unsigned PrintFromType : 1;
  unsigned ElideType : 1;
  unsigned ShowColors : 1;

  // The printer sets this variable to true if the template diff was used.
  unsigned TemplateDiffUsed : 1;
};

/// Special character that the diagnostic printer will use to toggle the bold
/// attribute.  The character itself will be not be printed.
const char ToggleHighlight = 127;

/// ProcessWarningOptions - Initialize the diagnostic client and process the
/// warning options specified on the command line.
void ProcessWarningOptions(DiagnosticsEngine &Diags,
                           const DiagnosticOptions &Opts,
                           bool ReportDiags = true);

} // namespace clang

#endif // LLVM_CLANG_BASIC_DIAGNOSTIC_H
