xref: /freebsd/contrib/llvm-project/clang/include/clang/Frontend/DiagnosticRenderer.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 
27 namespace clang {
28 
29 class LangOptions;
30 class SourceManager;
31 
32 using 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.
47 class DiagnosticRenderer {
48 protected:
49   const LangOptions &LangOpts;
50   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, DiagnosticOptions &DiagOpts);
72 
73   virtual ~DiagnosticRenderer();
74 
75   virtual void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
76                                      DiagnosticsEngine::Level Level,
77                                      StringRef Message,
78                                      ArrayRef<CharSourceRange> Ranges,
79                                      DiagOrStoredDiag Info) = 0;
80 
81   virtual void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
82                                  DiagnosticsEngine::Level Level,
83                                  ArrayRef<CharSourceRange> Ranges) = 0;
84 
85   virtual void emitCodeContext(FullSourceLoc Loc,
86                                DiagnosticsEngine::Level Level,
87                                SmallVectorImpl<CharSourceRange> &Ranges,
88                                ArrayRef<FixItHint> Hints) = 0;
89 
90   virtual void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) = 0;
91   virtual void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc,
92                                   StringRef ModuleName) = 0;
93   virtual void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc,
94                                           StringRef ModuleName) = 0;
95 
beginDiagnostic(DiagOrStoredDiag D,DiagnosticsEngine::Level Level)96   virtual void beginDiagnostic(DiagOrStoredDiag D,
97                                DiagnosticsEngine::Level Level) {}
endDiagnostic(DiagOrStoredDiag D,DiagnosticsEngine::Level Level)98   virtual void endDiagnostic(DiagOrStoredDiag D,
99                              DiagnosticsEngine::Level Level) {}
100 
101 private:
102   void emitBasicNote(StringRef Message);
103   void emitIncludeStack(FullSourceLoc Loc, PresumedLoc PLoc,
104                         DiagnosticsEngine::Level Level);
105   void emitIncludeStackRecursively(FullSourceLoc Loc);
106   void emitImportStack(FullSourceLoc Loc);
107   void emitImportStackRecursively(FullSourceLoc Loc, StringRef ModuleName);
108   void emitModuleBuildStack(const SourceManager &SM);
109   void emitCaret(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
110                  ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints);
111   void emitSingleMacroExpansion(FullSourceLoc Loc,
112                                 DiagnosticsEngine::Level Level,
113                                 ArrayRef<CharSourceRange> Ranges);
114   void emitMacroExpansions(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
115                            ArrayRef<CharSourceRange> Ranges,
116                            ArrayRef<FixItHint> Hints);
117 
118 public:
119   /// Emit a diagnostic.
120   ///
121   /// This is the primary entry point for emitting diagnostic messages.
122   /// It handles formatting and rendering the message as well as any ancillary
123   /// information needed based on macros whose expansions impact the
124   /// diagnostic.
125   ///
126   /// \param Loc The location for this caret.
127   /// \param Level The level of the diagnostic to be emitted.
128   /// \param Message The diagnostic message to emit.
129   /// \param Ranges The underlined ranges for this code snippet.
130   /// \param FixItHints The FixIt hints active for this diagnostic.
131   void emitDiagnostic(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
132                       StringRef Message, ArrayRef<CharSourceRange> Ranges,
133                       ArrayRef<FixItHint> FixItHints,
134                       DiagOrStoredDiag D = (Diagnostic *)nullptr);
135 
136   void emitStoredDiagnostic(StoredDiagnostic &Diag);
137 };
138 
139 /// Subclass of DiagnosticRender that turns all subdiagostics into explicit
140 /// notes.  It is up to subclasses to further define the behavior.
141 class DiagnosticNoteRenderer : public DiagnosticRenderer {
142 public:
DiagnosticNoteRenderer(const LangOptions & LangOpts,DiagnosticOptions & DiagOpts)143   DiagnosticNoteRenderer(const LangOptions &LangOpts,
144                          DiagnosticOptions &DiagOpts)
145       : DiagnosticRenderer(LangOpts, DiagOpts) {}
146 
147   ~DiagnosticNoteRenderer() override;
148 
149   void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override;
150 
151   void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc,
152                           StringRef ModuleName) override;
153 
154   void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc,
155                                   StringRef ModuleName) override;
156 
157   virtual void emitNote(FullSourceLoc Loc, StringRef Message) = 0;
158 };
159 
160 } // namespace clang
161 
162 #endif // LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
163