DiagnosticRenderer.h revision 830ea5b7c75413526c19531f0180fa6e45b98919
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/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///  Actual "printing" logic is implemented by subclasses.
35///
36/// This class provides an interface for building and emitting
37/// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt
38/// Hints, and code snippets. In the presence of macros this involves
39/// a recursive process, synthesizing notes for each macro expansion.
40///
41/// A brief worklist:
42/// FIXME: Sink the recursive printing of template instantiations into this
43/// class.
44class DiagnosticRenderer {
45protected:
46  const LangOptions &LangOpts;
47  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
48
49  /// \brief The location of the previous diagnostic if known.
50  ///
51  /// This will be invalid in cases where there is no (known) previous
52  /// diagnostic location, or that location itself is invalid or comes from
53  /// a different source manager than SM.
54  SourceLocation LastLoc;
55
56  /// \brief The location of the last include whose stack was printed if known.
57  ///
58  /// Same restriction as \see LastLoc essentially, but tracking include stack
59  /// root locations rather than diagnostic locations.
60  SourceLocation LastIncludeLoc;
61
62  /// \brief The level of the last diagnostic emitted.
63  ///
64  /// The level of the last diagnostic emitted. Used to detect level changes
65  /// which change the amount of information displayed.
66  DiagnosticsEngine::Level LastLevel;
67
68  DiagnosticRenderer(const LangOptions &LangOpts,
69                     DiagnosticOptions *DiagOpts);
70
71  virtual ~DiagnosticRenderer();
72
73  virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
74                                     DiagnosticsEngine::Level Level,
75                                     StringRef Message,
76                                     ArrayRef<CharSourceRange> Ranges,
77                                     const SourceManager *SM,
78                                     DiagOrStoredDiag Info) = 0;
79
80  virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
81                                 DiagnosticsEngine::Level Level,
82                                 ArrayRef<CharSourceRange> Ranges,
83                                 const SourceManager &SM) = 0;
84
85  virtual void emitBasicNote(StringRef Message) = 0;
86
87  virtual void emitCodeContext(SourceLocation Loc,
88                               DiagnosticsEngine::Level Level,
89                               SmallVectorImpl<CharSourceRange>& Ranges,
90                               ArrayRef<FixItHint> Hints,
91                               const SourceManager &SM) = 0;
92
93  virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
94                                   const SourceManager &SM) = 0;
95  virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
96                                          StringRef ModuleName,
97                                          const SourceManager &SM) = 0;
98
99  virtual void beginDiagnostic(DiagOrStoredDiag D,
100                               DiagnosticsEngine::Level Level) {}
101  virtual void endDiagnostic(DiagOrStoredDiag D,
102                             DiagnosticsEngine::Level Level) {}
103
104
105private:
106  void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level,
107                        const SourceManager &SM);
108  void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM);
109  void emitModuleBuildPath(const SourceManager &SM);
110  void emitMacroExpansionsAndCarets(SourceLocation Loc,
111                                    DiagnosticsEngine::Level Level,
112                                    SmallVectorImpl<CharSourceRange>& Ranges,
113                                    ArrayRef<FixItHint> Hints,
114                                    const SourceManager &SM,
115                                    unsigned &MacroDepth,
116                                    unsigned OnMacroInst = 0);
117public:
118  /// \brief Emit a diagnostic.
119  ///
120  /// This is the primary entry point for emitting diagnostic messages.
121  /// It handles formatting and rendering the message as well as any ancillary
122  /// information needed based on macros whose expansions impact the
123  /// diagnostic.
124  ///
125  /// \param Loc The location for this caret.
126  /// \param Level The level of the diagnostic to be emitted.
127  /// \param Message The diagnostic message to emit.
128  /// \param Ranges The underlined ranges for this code snippet.
129  /// \param FixItHints The FixIt hints active for this diagnostic.
130  /// \param SM The SourceManager; will be null if the diagnostic came from the
131  ///        frontend, thus \p Loc will be invalid.
132  void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level,
133                      StringRef Message, ArrayRef<CharSourceRange> Ranges,
134                      ArrayRef<FixItHint> FixItHints,
135                      const SourceManager *SM,
136                      DiagOrStoredDiag D = (Diagnostic *)0);
137
138  void emitStoredDiagnostic(StoredDiagnostic &Diag);
139};
140
141/// Subclass of DiagnosticRender that turns all subdiagostics into explicit
142/// notes.  It is up to subclasses to further define the behavior.
143class DiagnosticNoteRenderer : public DiagnosticRenderer {
144public:
145  DiagnosticNoteRenderer(const LangOptions &LangOpts,
146                         DiagnosticOptions *DiagOpts)
147    : DiagnosticRenderer(LangOpts, DiagOpts) {}
148
149  virtual ~DiagnosticNoteRenderer();
150
151  virtual void emitBasicNote(StringRef Message);
152
153  virtual void emitIncludeLocation(SourceLocation Loc,
154                                   PresumedLoc PLoc,
155                                   const SourceManager &SM);
156
157  virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
158                                          StringRef ModuleName,
159                                          const SourceManager &SM);
160
161  virtual void emitNote(SourceLocation Loc, StringRef Message,
162                        const SourceManager *SM) = 0;
163};
164} // end clang namespace
165#endif
166