aboutsummaryrefslogtreecommitdiff
path: root/include/clang/Frontend/DiagnosticRenderer.h
blob: fc9131b4bd7457356e16d6446b95396beaae37d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//===--- DiagnosticRenderer.h - Diagnostic Pretty-Printing ------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a utility class that provides support for pretty-printing of
// diagnostics. It is used to implement the different code paths which require
// such functionality in a consistent way.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTIC_RENDERER_H_
#define LLVM_CLANG_FRONTEND_DIAGNOSTIC_RENDERER_H_

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"

namespace clang {
  class DiagnosticOptions;
  class LangOptions;
  class SourceManager;

/// \brief Class to encapsulate the logic for formatting a diagnostic message.
///  Actual "printing" logic is implemented by subclasses.
///
/// This class provides an interface for building and emitting
/// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt
/// Hints, and code snippets. In the presence of macros this involves
/// a recursive process, synthesizing notes for each macro expansion.
///
/// A brief worklist:
/// FIXME: Sink the recursive printing of template instantiations into this
/// class.
class DiagnosticRenderer {
protected:
  const SourceManager &SM;
  const LangOptions &LangOpts;
  const DiagnosticOptions &DiagOpts;
  
  /// \brief The location of the previous diagnostic if known.
  ///
  /// This will be invalid in cases where there is no (known) previous
  /// diagnostic location, or that location itself is invalid or comes from
  /// a different source manager than SM.
  SourceLocation LastLoc;
  
  /// \brief The location of the last include whose stack was printed if known.
  ///
  /// Same restriction as \see LastLoc essentially, but tracking include stack
  /// root locations rather than diagnostic locations.
  SourceLocation LastIncludeLoc;
  
  /// \brief The level of the last diagnostic emitted.
  ///
  /// The level of the last diagnostic emitted. Used to detect level changes
  /// which change the amount of information displayed.
  DiagnosticsEngine::Level LastLevel;

  DiagnosticRenderer(const SourceManager &SM,
                     const LangOptions &LangOpts,
                     const DiagnosticOptions &DiagOpts);
  
  virtual ~DiagnosticRenderer();
  
  virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
                                     DiagnosticsEngine::Level Level,
                                     StringRef Message,
                                     ArrayRef<CharSourceRange> Ranges,
                                     const Diagnostic *Info) = 0;
  
  virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
                                 DiagnosticsEngine::Level Level,
                                 ArrayRef<CharSourceRange> Ranges) = 0;
  
  virtual void emitBasicNote(StringRef Message) = 0;
  
  virtual void emitCodeContext(SourceLocation Loc,
                               DiagnosticsEngine::Level Level,
                               SmallVectorImpl<CharSourceRange>& Ranges,
                               ArrayRef<FixItHint> Hints) = 0;
  
  virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc) = 0;
  
  virtual void beginDiagnostic(const Diagnostic *Info,
                               DiagnosticsEngine::Level Level) {}
  virtual void endDiagnostic(const Diagnostic *Info,
                             DiagnosticsEngine::Level Level) {}

  
private:
  void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level);
  void emitIncludeStackRecursively(SourceLocation Loc);
  void emitMacroExpansionsAndCarets(SourceLocation Loc,
                                    DiagnosticsEngine::Level Level,
                                    SmallVectorImpl<CharSourceRange>& Ranges,
                                    ArrayRef<FixItHint> Hints,
                                    unsigned &MacroDepth,
                                    unsigned OnMacroInst = 0);
public:
  /// \brief Emit a diagnostic.
  ///
  /// This is the primary entry point for emitting diagnostic messages.
  /// It handles formatting and rendering the message as well as any ancillary
  /// information needed based on macros whose expansions impact the
  /// diagnostic.
  ///
  /// \param Loc The location for this caret.
  /// \param Level The level of the diagnostic to be emitted.
  /// \param Message The diagnostic message to emit.
  /// \param Ranges The underlined ranges for this code snippet.
  /// \param FixItHints The FixIt hints active for this diagnostic.
  void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level,
                      StringRef Message, ArrayRef<CharSourceRange> Ranges,
                      ArrayRef<FixItHint> FixItHints,
                      const Diagnostic *Info = 0);
};
} // end clang namespace
#endif