//===--- DiagnosticRenderer.h - Diagnostic Pretty-Printing ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // 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_DIAGNOSTIC_RENDERER_H_ #define LLVM_CLANG_FRONTEND_DIAGNOSTIC_RENDERER_H_ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerUnion.h" namespace clang { class DiagnosticOptions; class LangOptions; class SourceManager; typedef llvm::PointerUnion DiagOrStoredDiag; /// \brief 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 DiagOpts; /// \brief 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; /// \brief 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; /// \brief 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; DiagnosticRenderer(const LangOptions &LangOpts, DiagnosticOptions *DiagOpts); virtual ~DiagnosticRenderer(); virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef Ranges, const SourceManager *SM, DiagOrStoredDiag Info) = 0; virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, ArrayRef Ranges, const SourceManager &SM) = 0; virtual void emitBasicNote(StringRef Message) = 0; virtual void emitCodeContext(SourceLocation Loc, DiagnosticsEngine::Level Level, SmallVectorImpl& Ranges, ArrayRef Hints, const SourceManager &SM) = 0; virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, const SourceManager &SM) = 0; virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, StringRef ModuleName, const SourceManager &SM) = 0; virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, StringRef ModuleName, const SourceManager &SM) = 0; virtual void beginDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level) {} virtual void endDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level) {} private: void emitIncludeStack(SourceLocation Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, const SourceManager &SM); void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM); void emitImportStack(SourceLocation Loc, const SourceManager &SM); void emitImportStackRecursively(SourceLocation Loc, StringRef ModuleName, const SourceManager &SM); void emitModuleBuildStack(const SourceManager &SM); void emitCaret(SourceLocation Loc, DiagnosticsEngine::Level Level, ArrayRef Ranges, ArrayRef Hints, const SourceManager &SM); void emitMacroExpansions(SourceLocation Loc, DiagnosticsEngine::Level Level, ArrayRef Ranges, ArrayRef Hints, const SourceManager &SM, unsigned &MacroDepth, unsigned OnMacroInst = 0); public: /// \brief 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. /// \param SM The SourceManager; will be null if the diagnostic came from the /// frontend, thus \p Loc will be invalid. void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef Ranges, ArrayRef FixItHints, const SourceManager *SM, DiagOrStoredDiag D = (Diagnostic *)0); 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) {} virtual ~DiagnosticNoteRenderer(); virtual void emitBasicNote(StringRef Message); virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, const SourceManager &SM); virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, StringRef ModuleName, const SourceManager &SM); virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, StringRef ModuleName, const SourceManager &SM); virtual void emitNote(SourceLocation Loc, StringRef Message, const SourceManager *SM) = 0; }; } // end clang namespace #endif