1//===- DiagnosticRenderer.h - Diagnostic Pretty-Printing --------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
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.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
16#define LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
17
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"
26
27namespace clang {
28
29class LangOptions;
30class SourceManager;
31
32using DiagOrStoredDiag =
33 llvm::PointerUnion<const Diagnostic *, const StoredDiagnostic *>;
34
35/// Class to encapsulate the logic for formatting a diagnostic message.
36///
37/// Actual "printing" logic is implemented by subclasses.
38///
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.
43///
44/// A brief worklist:
45/// FIXME: Sink the recursive printing of template instantiations into this
46/// class.
47class DiagnosticRenderer {
48protected:
49 const LangOptions &LangOpts;
50 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
51
52 /// The location of the previous diagnostic if known.
53 ///
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;
58
59 /// The location of the last include whose stack was printed if known.
60 ///
61 /// Same restriction as LastLoc essentially, but tracking include stack
62 /// root locations rather than diagnostic locations.
63 SourceLocation LastIncludeLoc;
64
65 /// The level of the last diagnostic emitted.
66 ///
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;
70
71 DiagnosticRenderer(const LangOptions &LangOpts,
72 DiagnosticOptions *DiagOpts);
73
74 virtual ~DiagnosticRenderer();
75
76 virtual void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
77 DiagnosticsEngine::Level Level,
78 StringRef Message,
79 ArrayRef<CharSourceRange> Ranges,
80 DiagOrStoredDiag Info) = 0;
81
82 virtual void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
83 DiagnosticsEngine::Level Level,
84 ArrayRef<CharSourceRange> Ranges) = 0;
85
86 virtual void emitCodeContext(FullSourceLoc Loc,
87 DiagnosticsEngine::Level Level,
88 SmallVectorImpl<CharSourceRange> &Ranges,
89 ArrayRef<FixItHint> Hints) = 0;
90
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;
96
97 virtual void beginDiagnostic(DiagOrStoredDiag D,
98 DiagnosticsEngine::Level Level) {}
99 virtual void endDiagnostic(DiagOrStoredDiag D,
100 DiagnosticsEngine::Level Level) {}
101
102private:
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);
118
119public:
120 /// Emit a diagnostic.
121 ///
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
125 /// diagnostic.
126 ///
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);
136
137 void emitStoredDiagnostic(StoredDiagnostic &Diag);
138};
139
140/// Subclass of DiagnosticRender that turns all subdiagostics into explicit
141/// notes. It is up to subclasses to further define the behavior.
142class DiagnosticNoteRenderer : public DiagnosticRenderer {
143public:
144 DiagnosticNoteRenderer(const LangOptions &LangOpts,
145 DiagnosticOptions *DiagOpts)
146 : DiagnosticRenderer(LangOpts, DiagOpts) {}
147
148 ~DiagnosticNoteRenderer() override;
149
150 void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override;
151
152 void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc,
153 StringRef ModuleName) override;
154
155 void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc,
156 StringRef ModuleName) override;
157
158 virtual void emitNote(FullSourceLoc Loc, StringRef Message) = 0;
159};
160
161} // namespace clang
162
163#endif // LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
164

source code of clang/include/clang/Frontend/DiagnosticRenderer.h