llvm/clang/include/clang/Basic/Diagnostic.h

//===- 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/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 <optional>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>

namespace llvm {
class Error;
class raw_ostream;
} // namespace llvm

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 {};

struct DiagnosticStorage {};

/// An allocator for DiagnosticStorage objects, which uses a small cache to
/// objects, used to reduce malloc()/free() traffic for partial diagnostics.
class DiagStorageAllocator {};

/// 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> {};

/// 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 {};

/// 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 {};

//===----------------------------------------------------------------------===//
// 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 {};

struct AddFlagValue {};

/// 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) {}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             StringRef S) {}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             const char *Str) {}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             int I) {}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             long I) {}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             long long I) {}

// 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) {}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             unsigned I) {}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             unsigned long I) {}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             unsigned long long I) {}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             tok::TokenKind I) {}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             const IdentifierInfo *II) {}

// 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) {}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             SourceLocation L) {}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             SourceRange R) {}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             ArrayRef<SourceRange> Ranges) {}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             const CharSourceRange &R) {}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             const FixItHint &Hint) {}

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                             ArrayRef<FixItHint> Hints) {}

inline const StreamingDiagnostic &
operator<<(const StreamingDiagnostic &DB,
           const std::optional<SourceRange> &Opt) {}

inline const StreamingDiagnostic &
operator<<(const StreamingDiagnostic &DB,
           const std::optional<CharSourceRange> &Opt) {}

inline const StreamingDiagnostic &
operator<<(const StreamingDiagnostic &DB, const std::optional<FixItHint> &Opt) {}

/// A nullability kind paired with a bit indicating whether it used a
/// context-sensitive keyword.
DiagNullabilityKind;

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

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

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

inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) {}

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

/// A little helper class (which is basically a smart pointer that forwards
/// info from DiagnosticsEngine and DiagnosticStorage) that allows clients to
/// enquire about the diagnostic.
class Diagnostic {};

/**
 * Represents a diagnostic in a form that can be retained until its
 * corresponding source manager is destroyed.
 */
class StoredDiagnostic {};

// Simple debug printing of StoredDiagnostic.
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const StoredDiagnostic &);

/// Abstract interface, implemented by clients of the front-end, which
/// formats and prints fully processed diagnostics.
class DiagnosticConsumer {};

/// A diagnostic client that ignores all diagnostics.
class IgnoringDiagConsumer : public DiagnosticConsumer {};

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

// Struct used for sending info about how a type should be printed.
struct TemplateDiffTypes {};

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

/// 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);
void EscapeStringForDiagnostic(StringRef Str, SmallVectorImpl<char> &OutStr);
} // namespace clang

#endif // LLVM_CLANG_BASIC_DIAGNOSTIC_H