DiagnosticRenderer.h revision 6c3254316de2d0d554b19702f4b10117ae46b77b
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_DIAGNOSTIC_RENDERER_H_
17#define LLVM_CLANG_FRONTEND_DIAGNOSTIC_RENDERER_H_
18
19#include "clang/Basic/Diagnostic.h"
20#include "clang/Basic/LLVM.h"
21#include "clang/Basic/SourceLocation.h"
22#include "llvm/ADT/Optional.h"
23#include "llvm/ADT/PointerUnion.h"
24
25namespace clang {
26
27class DiagnosticOptions;
28class LangOptions;
29class SourceManager;
30
31typedef llvm::PointerUnion<const Diagnostic *,
32                           const StoredDiagnostic *> DiagOrStoredDiag;
33
34/// \brief Class to encapsulate the logic for formatting a diagnostic message.
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 \see 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(SourceLocation Loc, PresumedLoc PLoc,
75                                     DiagnosticsEngine::Level Level,
76                                     StringRef Message,
77                                     ArrayRef<CharSourceRange> Ranges,
78                                     const SourceManager *SM,
79                                     DiagOrStoredDiag Info) = 0;
80
81  virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
82                                 DiagnosticsEngine::Level Level,
83                                 ArrayRef<CharSourceRange> Ranges,
84                                 const SourceManager &SM) = 0;
85
86  virtual void emitBasicNote(StringRef Message) = 0;
87
88  virtual void emitCodeContext(SourceLocation Loc,
89                               DiagnosticsEngine::Level Level,
90                               SmallVectorImpl<CharSourceRange>& Ranges,
91                               ArrayRef<FixItHint> Hints,
92                               const SourceManager &SM) = 0;
93
94  virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
95                                   const SourceManager &SM) = 0;
96  virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
97                                  StringRef ModuleName,
98                                  const SourceManager &SM) = 0;
99  virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
100                                          StringRef ModuleName,
101                                          const SourceManager &SM) = 0;
102
103  virtual void beginDiagnostic(DiagOrStoredDiag D,
104                               DiagnosticsEngine::Level Level) {}
105  virtual void endDiagnostic(DiagOrStoredDiag D,
106                             DiagnosticsEngine::Level Level) {}
107
108
109private:
110  void emitIncludeStack(SourceLocation Loc, PresumedLoc PLoc,
111                        DiagnosticsEngine::Level Level, const SourceManager &SM);
112  void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM);
113  void emitImportStack(SourceLocation Loc, const SourceManager &SM);
114  void emitImportStackRecursively(SourceLocation Loc, StringRef ModuleName,
115                                  const SourceManager &SM);
116  void emitModuleBuildPath(const SourceManager &SM);
117  void emitMacroExpansionsAndCarets(SourceLocation Loc,
118                                    DiagnosticsEngine::Level Level,
119                                    SmallVectorImpl<CharSourceRange>& Ranges,
120                                    ArrayRef<FixItHint> Hints,
121                                    const SourceManager &SM,
122                                    unsigned &MacroDepth,
123                                    unsigned OnMacroInst = 0);
124public:
125  /// \brief Emit a diagnostic.
126  ///
127  /// This is the primary entry point for emitting diagnostic messages.
128  /// It handles formatting and rendering the message as well as any ancillary
129  /// information needed based on macros whose expansions impact the
130  /// diagnostic.
131  ///
132  /// \param Loc The location for this caret.
133  /// \param Level The level of the diagnostic to be emitted.
134  /// \param Message The diagnostic message to emit.
135  /// \param Ranges The underlined ranges for this code snippet.
136  /// \param FixItHints The FixIt hints active for this diagnostic.
137  /// \param SM The SourceManager; will be null if the diagnostic came from the
138  ///        frontend, thus \p Loc will be invalid.
139  void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level,
140                      StringRef Message, ArrayRef<CharSourceRange> Ranges,
141                      ArrayRef<FixItHint> FixItHints,
142                      const SourceManager *SM,
143                      DiagOrStoredDiag D = (Diagnostic *)0);
144
145  void emitStoredDiagnostic(StoredDiagnostic &Diag);
146};
147
148/// Subclass of DiagnosticRender that turns all subdiagostics into explicit
149/// notes.  It is up to subclasses to further define the behavior.
150class DiagnosticNoteRenderer : public DiagnosticRenderer {
151public:
152  DiagnosticNoteRenderer(const LangOptions &LangOpts,
153                         DiagnosticOptions *DiagOpts)
154    : DiagnosticRenderer(LangOpts, DiagOpts) {}
155
156  virtual ~DiagnosticNoteRenderer();
157
158  virtual void emitBasicNote(StringRef Message);
159
160  virtual void emitIncludeLocation(SourceLocation Loc,
161                                   PresumedLoc PLoc,
162                                   const SourceManager &SM);
163
164  virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
165                                  StringRef ModuleName,
166                                  const SourceManager &SM);
167
168  virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
169                                          StringRef ModuleName,
170                                          const SourceManager &SM);
171
172  virtual void emitNote(SourceLocation Loc, StringRef Message,
173                        const SourceManager *SM) = 0;
174};
175} // end clang namespace
176#endif
177