Viewing file: DiagnosticRenderer.h (6.69 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
//===- DiagnosticRenderer.h - Diagnostic Pretty-Printing --------*- 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 // //===----------------------------------------------------------------------===// // // This is a utility class that provides support for pretty-printing of // diagnostics. It is used to implement the different code paths which require // such functionality in a consistent way. // //===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H #define LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
#include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/StringRef.h"
namespace clang {
class LangOptions; class SourceManager;
using DiagOrStoredDiag = llvm::PointerUnion<const Diagnostic *, const StoredDiagnostic *>;
/// Class to encapsulate the logic for formatting a diagnostic message. /// /// Actual "printing" logic is implemented by subclasses. /// /// This class provides an interface for building and emitting /// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt /// Hints, and code snippets. In the presence of macros this involves /// a recursive process, synthesizing notes for each macro expansion. /// /// A brief worklist: /// FIXME: Sink the recursive printing of template instantiations into this /// class. class DiagnosticRenderer { protected: const LangOptions &LangOpts; IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
/// The location of the previous diagnostic if known. /// /// This will be invalid in cases where there is no (known) previous /// diagnostic location, or that location itself is invalid or comes from /// a different source manager than SM. SourceLocation LastLoc;
/// The location of the last include whose stack was printed if known. /// /// Same restriction as LastLoc essentially, but tracking include stack /// root locations rather than diagnostic locations. SourceLocation LastIncludeLoc;
/// The level of the last diagnostic emitted. /// /// The level of the last diagnostic emitted. Used to detect level changes /// which change the amount of information displayed. DiagnosticsEngine::Level LastLevel = DiagnosticsEngine::Ignored;
DiagnosticRenderer(const LangOptions &LangOpts, DiagnosticOptions *DiagOpts);
virtual ~DiagnosticRenderer();
virtual void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef<CharSourceRange> Ranges, DiagOrStoredDiag Info) = 0;
virtual void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, ArrayRef<CharSourceRange> Ranges) = 0;
virtual void emitCodeContext(FullSourceLoc Loc, DiagnosticsEngine::Level Level, SmallVectorImpl<CharSourceRange> &Ranges, ArrayRef<FixItHint> Hints) = 0;
virtual void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) = 0; virtual void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName) = 0; virtual void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName) = 0;
virtual void beginDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level) {} virtual void endDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level) {}
private: void emitBasicNote(StringRef Message); void emitIncludeStack(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level); void emitIncludeStackRecursively(FullSourceLoc Loc); void emitImportStack(FullSourceLoc Loc); void emitImportStackRecursively(FullSourceLoc Loc, StringRef ModuleName); void emitModuleBuildStack(const SourceManager &SM); void emitCaret(FullSourceLoc Loc, DiagnosticsEngine::Level Level, ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints); void emitSingleMacroExpansion(FullSourceLoc Loc, DiagnosticsEngine::Level Level, ArrayRef<CharSourceRange> Ranges); void emitMacroExpansions(FullSourceLoc Loc, DiagnosticsEngine::Level Level, ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints);
public: /// Emit a diagnostic. /// /// This is the primary entry point for emitting diagnostic messages. /// It handles formatting and rendering the message as well as any ancillary /// information needed based on macros whose expansions impact the /// diagnostic. /// /// \param Loc The location for this caret. /// \param Level The level of the diagnostic to be emitted. /// \param Message The diagnostic message to emit. /// \param Ranges The underlined ranges for this code snippet. /// \param FixItHints The FixIt hints active for this diagnostic. void emitDiagnostic(FullSourceLoc Loc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> FixItHints, DiagOrStoredDiag D = (Diagnostic *)nullptr);
void emitStoredDiagnostic(StoredDiagnostic &Diag); };
/// Subclass of DiagnosticRender that turns all subdiagostics into explicit /// notes. It is up to subclasses to further define the behavior. class DiagnosticNoteRenderer : public DiagnosticRenderer { public: DiagnosticNoteRenderer(const LangOptions &LangOpts, DiagnosticOptions *DiagOpts) : DiagnosticRenderer(LangOpts, DiagOpts) {}
~DiagnosticNoteRenderer() override;
void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override;
void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName) override;
void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc, StringRef ModuleName) override;
virtual void emitNote(FullSourceLoc Loc, StringRef Message) = 0; };
} // namespace clang
#endif // LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
|