Clang Project

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