1//===--- DiagnosticRenderer.h - Diagnostic Pretty-Printing ------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This is a utility class that provides support for pretty-printing of
11// diagnostics. It is used to implement the different code paths which require
12// such functionality in a consistent way.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
17#define LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
18
19#include "clang/Basic/Diagnostic.h"
20#include "clang/Basic/LLVM.h"
21#include "clang/Basic/SourceLocation.h"
22#include "llvm/ADT/PointerUnion.h"
23
24namespace clang {
25
26class DiagnosticOptions;
27class LangOptions;
28class SourceManager;
29
30typedef llvm::PointerUnion<const Diagnostic *,
31                           const StoredDiagnostic *> DiagOrStoredDiag;
32
33/// \brief Class to encapsulate the logic for formatting a diagnostic message.
34///
35/// Actual "printing" logic is implemented by subclasses.
36///
37/// This class provides an interface for building and emitting
38/// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt
39/// Hints, and code snippets. In the presence of macros this involves
40/// a recursive process, synthesizing notes for each macro expansion.
41///
42/// A brief worklist:
43/// FIXME: Sink the recursive printing of template instantiations into this
44/// class.
45class DiagnosticRenderer {
46protected:
47  const LangOptions &LangOpts;
48  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
49
50  /// \brief The location of the previous diagnostic if known.
51  ///
52  /// This will be invalid in cases where there is no (known) previous
53  /// diagnostic location, or that location itself is invalid or comes from
54  /// a different source manager than SM.
55  SourceLocation LastLoc;
56
57  /// \brief The location of the last include whose stack was printed if known.
58  ///
59  /// Same restriction as LastLoc essentially, but tracking include stack
60  /// root locations rather than diagnostic locations.
61  SourceLocation LastIncludeLoc;
62
63  /// \brief The level of the last diagnostic emitted.
64  ///
65  /// The level of the last diagnostic emitted. Used to detect level changes
66  /// which change the amount of information displayed.
67  DiagnosticsEngine::Level LastLevel;
68
69  DiagnosticRenderer(const LangOptions &LangOpts,
70                     DiagnosticOptions *DiagOpts);
71
72  virtual ~DiagnosticRenderer();
73
74  virtual void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
75                                     DiagnosticsEngine::Level Level,
76                                     StringRef Message,
77                                     ArrayRef<CharSourceRange> Ranges,
78                                     DiagOrStoredDiag Info) = 0;
79
80  virtual void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
81                                 DiagnosticsEngine::Level Level,
82                                 ArrayRef<CharSourceRange> Ranges) = 0;
83
84  virtual void emitCodeContext(FullSourceLoc Loc,
85                               DiagnosticsEngine::Level Level,
86                               SmallVectorImpl<CharSourceRange> &Ranges,
87                               ArrayRef<FixItHint> Hints) = 0;
88
89  virtual void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) = 0;
90  virtual void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc,
91                                  StringRef ModuleName) = 0;
92  virtual void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc,
93                                          StringRef ModuleName) = 0;
94
95  virtual void beginDiagnostic(DiagOrStoredDiag D,
96                               DiagnosticsEngine::Level Level) {}
97  virtual void endDiagnostic(DiagOrStoredDiag D,
98                             DiagnosticsEngine::Level Level) {}
99
100
101private:
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
118public:
119  /// \brief 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.
141class DiagnosticNoteRenderer : public DiagnosticRenderer {
142public:
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} // end clang namespace
160#endif
161