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