DiagnosticRenderer.h revision 6c3254316de2d0d554b19702f4b10117ae46b77b
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_DIAGNOSTIC_RENDERER_H_ 17#define LLVM_CLANG_FRONTEND_DIAGNOSTIC_RENDERER_H_ 18 19#include "clang/Basic/Diagnostic.h" 20#include "clang/Basic/LLVM.h" 21#include "clang/Basic/SourceLocation.h" 22#include "llvm/ADT/Optional.h" 23#include "llvm/ADT/PointerUnion.h" 24 25namespace clang { 26 27class DiagnosticOptions; 28class LangOptions; 29class SourceManager; 30 31typedef llvm::PointerUnion<const Diagnostic *, 32 const StoredDiagnostic *> DiagOrStoredDiag; 33 34/// \brief Class to encapsulate the logic for formatting a diagnostic message. 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 \see 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(SourceLocation Loc, PresumedLoc PLoc, 75 DiagnosticsEngine::Level Level, 76 StringRef Message, 77 ArrayRef<CharSourceRange> Ranges, 78 const SourceManager *SM, 79 DiagOrStoredDiag Info) = 0; 80 81 virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, 82 DiagnosticsEngine::Level Level, 83 ArrayRef<CharSourceRange> Ranges, 84 const SourceManager &SM) = 0; 85 86 virtual void emitBasicNote(StringRef Message) = 0; 87 88 virtual void emitCodeContext(SourceLocation Loc, 89 DiagnosticsEngine::Level Level, 90 SmallVectorImpl<CharSourceRange>& Ranges, 91 ArrayRef<FixItHint> Hints, 92 const SourceManager &SM) = 0; 93 94 virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, 95 const SourceManager &SM) = 0; 96 virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, 97 StringRef ModuleName, 98 const SourceManager &SM) = 0; 99 virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, 100 StringRef ModuleName, 101 const SourceManager &SM) = 0; 102 103 virtual void beginDiagnostic(DiagOrStoredDiag D, 104 DiagnosticsEngine::Level Level) {} 105 virtual void endDiagnostic(DiagOrStoredDiag D, 106 DiagnosticsEngine::Level Level) {} 107 108 109private: 110 void emitIncludeStack(SourceLocation Loc, PresumedLoc PLoc, 111 DiagnosticsEngine::Level Level, const SourceManager &SM); 112 void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM); 113 void emitImportStack(SourceLocation Loc, const SourceManager &SM); 114 void emitImportStackRecursively(SourceLocation Loc, StringRef ModuleName, 115 const SourceManager &SM); 116 void emitModuleBuildPath(const SourceManager &SM); 117 void emitMacroExpansionsAndCarets(SourceLocation Loc, 118 DiagnosticsEngine::Level Level, 119 SmallVectorImpl<CharSourceRange>& Ranges, 120 ArrayRef<FixItHint> Hints, 121 const SourceManager &SM, 122 unsigned &MacroDepth, 123 unsigned OnMacroInst = 0); 124public: 125 /// \brief Emit a diagnostic. 126 /// 127 /// This is the primary entry point for emitting diagnostic messages. 128 /// It handles formatting and rendering the message as well as any ancillary 129 /// information needed based on macros whose expansions impact the 130 /// diagnostic. 131 /// 132 /// \param Loc The location for this caret. 133 /// \param Level The level of the diagnostic to be emitted. 134 /// \param Message The diagnostic message to emit. 135 /// \param Ranges The underlined ranges for this code snippet. 136 /// \param FixItHints The FixIt hints active for this diagnostic. 137 /// \param SM The SourceManager; will be null if the diagnostic came from the 138 /// frontend, thus \p Loc will be invalid. 139 void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level, 140 StringRef Message, ArrayRef<CharSourceRange> Ranges, 141 ArrayRef<FixItHint> FixItHints, 142 const SourceManager *SM, 143 DiagOrStoredDiag D = (Diagnostic *)0); 144 145 void emitStoredDiagnostic(StoredDiagnostic &Diag); 146}; 147 148/// Subclass of DiagnosticRender that turns all subdiagostics into explicit 149/// notes. It is up to subclasses to further define the behavior. 150class DiagnosticNoteRenderer : public DiagnosticRenderer { 151public: 152 DiagnosticNoteRenderer(const LangOptions &LangOpts, 153 DiagnosticOptions *DiagOpts) 154 : DiagnosticRenderer(LangOpts, DiagOpts) {} 155 156 virtual ~DiagnosticNoteRenderer(); 157 158 virtual void emitBasicNote(StringRef Message); 159 160 virtual void emitIncludeLocation(SourceLocation Loc, 161 PresumedLoc PLoc, 162 const SourceManager &SM); 163 164 virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, 165 StringRef ModuleName, 166 const SourceManager &SM); 167 168 virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, 169 StringRef ModuleName, 170 const SourceManager &SM); 171 172 virtual void emitNote(SourceLocation Loc, StringRef Message, 173 const SourceManager *SM) = 0; 174}; 175} // end clang namespace 176#endif 177