1//===--- DiagnosticRenderer.h - Diagnostic Pretty-Printing ------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This is a utility class that provides support for pretty-printing of 11// diagnostics. It is used to implement the different code paths which require 12// such functionality in a consistent way. 13// 14//===----------------------------------------------------------------------===// 15 16#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H 17#define LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H 18 19#include "clang/Basic/Diagnostic.h" 20#include "clang/Basic/LLVM.h" 21#include "clang/Basic/SourceLocation.h" 22#include "llvm/ADT/PointerUnion.h" 23 24namespace clang { 25 26class DiagnosticOptions; 27class LangOptions; 28class SourceManager; 29 30typedef llvm::PointerUnion<const Diagnostic *, 31 const StoredDiagnostic *> DiagOrStoredDiag; 32 33/// \brief Class to encapsulate the logic for formatting a diagnostic message. 34/// 35/// Actual "printing" logic is implemented by subclasses. 36/// 37/// This class provides an interface for building and emitting 38/// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt 39/// Hints, and code snippets. In the presence of macros this involves 40/// a recursive process, synthesizing notes for each macro expansion. 41/// 42/// A brief worklist: 43/// FIXME: Sink the recursive printing of template instantiations into this 44/// class. 45class DiagnosticRenderer { 46protected: 47 const LangOptions &LangOpts; 48 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; 49 50 /// \brief The location of the previous diagnostic if known. 51 /// 52 /// This will be invalid in cases where there is no (known) previous 53 /// diagnostic location, or that location itself is invalid or comes from 54 /// a different source manager than SM. 55 SourceLocation LastLoc; 56 57 /// \brief The location of the last include whose stack was printed if known. 58 /// 59 /// Same restriction as LastLoc essentially, but tracking include stack 60 /// root locations rather than diagnostic locations. 61 SourceLocation LastIncludeLoc; 62 63 /// \brief The level of the last diagnostic emitted. 64 /// 65 /// The level of the last diagnostic emitted. Used to detect level changes 66 /// which change the amount of information displayed. 67 DiagnosticsEngine::Level LastLevel; 68 69 DiagnosticRenderer(const LangOptions &LangOpts, 70 DiagnosticOptions *DiagOpts); 71 72 virtual ~DiagnosticRenderer(); 73 74 virtual void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, 75 DiagnosticsEngine::Level Level, 76 StringRef Message, 77 ArrayRef<CharSourceRange> Ranges, 78 DiagOrStoredDiag Info) = 0; 79 80 virtual void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, 81 DiagnosticsEngine::Level Level, 82 ArrayRef<CharSourceRange> Ranges) = 0; 83 84 virtual void emitCodeContext(FullSourceLoc Loc, 85 DiagnosticsEngine::Level Level, 86 SmallVectorImpl<CharSourceRange> &Ranges, 87 ArrayRef<FixItHint> Hints) = 0; 88 89 virtual void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) = 0; 90 virtual void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, 91 StringRef ModuleName) = 0; 92 virtual void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc, 93 StringRef ModuleName) = 0; 94 95 virtual void beginDiagnostic(DiagOrStoredDiag D, 96 DiagnosticsEngine::Level Level) {} 97 virtual void endDiagnostic(DiagOrStoredDiag D, 98 DiagnosticsEngine::Level Level) {} 99 100 101private: 102 void emitBasicNote(StringRef Message); 103 void emitIncludeStack(FullSourceLoc Loc, PresumedLoc PLoc, 104 DiagnosticsEngine::Level Level); 105 void emitIncludeStackRecursively(FullSourceLoc Loc); 106 void emitImportStack(FullSourceLoc Loc); 107 void emitImportStackRecursively(FullSourceLoc Loc, StringRef ModuleName); 108 void emitModuleBuildStack(const SourceManager &SM); 109 void emitCaret(FullSourceLoc Loc, DiagnosticsEngine::Level Level, 110 ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints); 111 void emitSingleMacroExpansion(FullSourceLoc Loc, 112 DiagnosticsEngine::Level Level, 113 ArrayRef<CharSourceRange> Ranges); 114 void emitMacroExpansions(FullSourceLoc Loc, DiagnosticsEngine::Level Level, 115 ArrayRef<CharSourceRange> Ranges, 116 ArrayRef<FixItHint> Hints); 117 118public: 119 /// \brief Emit a diagnostic. 120 /// 121 /// This is the primary entry point for emitting diagnostic messages. 122 /// It handles formatting and rendering the message as well as any ancillary 123 /// information needed based on macros whose expansions impact the 124 /// diagnostic. 125 /// 126 /// \param Loc The location for this caret. 127 /// \param Level The level of the diagnostic to be emitted. 128 /// \param Message The diagnostic message to emit. 129 /// \param Ranges The underlined ranges for this code snippet. 130 /// \param FixItHints The FixIt hints active for this diagnostic. 131 void emitDiagnostic(FullSourceLoc Loc, DiagnosticsEngine::Level Level, 132 StringRef Message, ArrayRef<CharSourceRange> Ranges, 133 ArrayRef<FixItHint> FixItHints, 134 DiagOrStoredDiag D = (Diagnostic *)nullptr); 135 136 void emitStoredDiagnostic(StoredDiagnostic &Diag); 137}; 138 139/// Subclass of DiagnosticRender that turns all subdiagostics into explicit 140/// notes. It is up to subclasses to further define the behavior. 141class DiagnosticNoteRenderer : public DiagnosticRenderer { 142public: 143 DiagnosticNoteRenderer(const LangOptions &LangOpts, 144 DiagnosticOptions *DiagOpts) 145 : DiagnosticRenderer(LangOpts, DiagOpts) {} 146 147 ~DiagnosticNoteRenderer() override; 148 149 void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override; 150 151 void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc, 152 StringRef ModuleName) override; 153 154 void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc, 155 StringRef ModuleName) override; 156 157 virtual void emitNote(FullSourceLoc Loc, StringRef Message) = 0; 158}; 159} // end clang namespace 160#endif 161