//===- 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