xref: /freebsd/contrib/llvm-project/clang/include/clang/Frontend/DiagnosticRenderer.h (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
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