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