12898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek//===--- DiagnosticRenderer.h - Diagnostic Pretty-Printing ------*- C++ -*-===//
22898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek//
32898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek//                     The LLVM Compiler Infrastructure
42898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek//
52898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// This file is distributed under the University of Illinois Open Source
62898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// License. See LICENSE.TXT for details.
72898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek//
82898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek//===----------------------------------------------------------------------===//
92898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek//
102898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// This is a utility class that provides support for pretty-printing of
112898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// diagnostics. It is used to implement the different code paths which require
122898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// such functionality in a consistent way.
132898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek//
142898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek//===----------------------------------------------------------------------===//
152898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
162898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTIC_RENDERER_H_
172898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#define LLVM_CLANG_FRONTEND_DIAGNOSTIC_RENDERER_H_
182898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
192898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "clang/Basic/Diagnostic.h"
202898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "clang/Basic/LLVM.h"
212898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "clang/Basic/SourceLocation.h"
226c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor#include "llvm/ADT/Optional.h"
238be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek#include "llvm/ADT/PointerUnion.h"
242898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
252898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremeneknamespace clang {
262898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
278be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekclass DiagnosticOptions;
288be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekclass LangOptions;
298be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekclass SourceManager;
308be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek
318be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenektypedef llvm::PointerUnion<const Diagnostic *,
328be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek                           const StoredDiagnostic *> DiagOrStoredDiag;
338be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek
342898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \brief Class to encapsulate the logic for formatting a diagnostic message.
35c34464ee3367de42c477561c0ae069675be8393cJames Dennett///
36c34464ee3367de42c477561c0ae069675be8393cJames Dennett/// Actual "printing" logic is implemented by subclasses.
372898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek///
382898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// This class provides an interface for building and emitting
392898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt
402898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// Hints, and code snippets. In the presence of macros this involves
412898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// a recursive process, synthesizing notes for each macro expansion.
422898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek///
432898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// A brief worklist:
442898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// FIXME: Sink the recursive printing of template instantiations into this
452898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// class.
462898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekclass DiagnosticRenderer {
472898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekprotected:
482898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  const LangOptions &LangOpts;
4902c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
502898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
512898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \brief The location of the previous diagnostic if known.
522898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  ///
532898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// This will be invalid in cases where there is no (known) previous
542898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// diagnostic location, or that location itself is invalid or comes from
552898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// a different source manager than SM.
562898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  SourceLocation LastLoc;
572898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
582898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \brief The location of the last include whose stack was printed if known.
592898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  ///
60c34464ee3367de42c477561c0ae069675be8393cJames Dennett  /// Same restriction as LastLoc essentially, but tracking include stack
612898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// root locations rather than diagnostic locations.
622898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  SourceLocation LastIncludeLoc;
632898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
642898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \brief The level of the last diagnostic emitted.
652898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  ///
662898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// The level of the last diagnostic emitted. Used to detect level changes
672898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// which change the amount of information displayed.
682898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  DiagnosticsEngine::Level LastLevel;
692898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
7016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  DiagnosticRenderer(const LangOptions &LangOpts,
7102c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor                     DiagnosticOptions *DiagOpts);
722898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
732898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  virtual ~DiagnosticRenderer();
742898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
752898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
762898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                     DiagnosticsEngine::Level Level,
772898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                     StringRef Message,
782898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                     ArrayRef<CharSourceRange> Ranges,
7916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                     const SourceManager *SM,
808be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek                                     DiagOrStoredDiag Info) = 0;
812898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
822898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
832898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                 DiagnosticsEngine::Level Level,
8416afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                 ArrayRef<CharSourceRange> Ranges,
8516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                 const SourceManager &SM) = 0;
86ef8225444452a1486bd721f3285301fe84643b00Stephen Hines
872898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  virtual void emitCodeContext(SourceLocation Loc,
882898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                               DiagnosticsEngine::Level Level,
892898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                               SmallVectorImpl<CharSourceRange>& Ranges,
9016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                               ArrayRef<FixItHint> Hints,
9116afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                               const SourceManager &SM) = 0;
922898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
9316afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
9416afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                   const SourceManager &SM) = 0;
956c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor  virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
966c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor                                  StringRef ModuleName,
976c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor                                  const SourceManager &SM) = 0;
98830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor  virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
99830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor                                          StringRef ModuleName,
100830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor                                          const SourceManager &SM) = 0;
101830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor
1028be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek  virtual void beginDiagnostic(DiagOrStoredDiag D,
1032898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                               DiagnosticsEngine::Level Level) {}
1048be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek  virtual void endDiagnostic(DiagOrStoredDiag D,
1052898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                             DiagnosticsEngine::Level Level) {}
1062898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
1072898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
1082898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekprivate:
109ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  void emitBasicNote(StringRef Message);
1106c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor  void emitIncludeStack(SourceLocation Loc, PresumedLoc PLoc,
1116c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor                        DiagnosticsEngine::Level Level, const SourceManager &SM);
11216afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM);
1136c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor  void emitImportStack(SourceLocation Loc, const SourceManager &SM);
1146c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor  void emitImportStackRecursively(SourceLocation Loc, StringRef ModuleName,
1156c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor                                  const SourceManager &SM);
1164565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor  void emitModuleBuildStack(const SourceManager &SM);
117ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith  void emitCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
118ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith                 ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints,
119ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith                 const SourceManager &SM);
120ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith  void emitMacroExpansions(SourceLocation Loc,
121ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith                           DiagnosticsEngine::Level Level,
122ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith                           ArrayRef<CharSourceRange> Ranges,
123ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith                           ArrayRef<FixItHint> Hints,
124ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith                           const SourceManager &SM,
125ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith                           unsigned &MacroDepth,
126ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith                           unsigned OnMacroInst = 0);
1272898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekpublic:
1282898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \brief Emit a diagnostic.
1292898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  ///
1302898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// This is the primary entry point for emitting diagnostic messages.
1312898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// It handles formatting and rendering the message as well as any ancillary
1322898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// information needed based on macros whose expansions impact the
1332898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// diagnostic.
1342898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  ///
1352898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \param Loc The location for this caret.
1362898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \param Level The level of the diagnostic to be emitted.
1372898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \param Message The diagnostic message to emit.
1382898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \param Ranges The underlined ranges for this code snippet.
1392898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \param FixItHints The FixIt hints active for this diagnostic.
14016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  /// \param SM The SourceManager; will be null if the diagnostic came from the
14170517ca5c07c4b41ff8662b94ee22047b0299f8cDmitri Gribenko  ///        frontend, thus \p Loc will be invalid.
1422898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level,
1432898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                      StringRef Message, ArrayRef<CharSourceRange> Ranges,
1442898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                      ArrayRef<FixItHint> FixItHints,
14516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                      const SourceManager *SM,
1466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                      DiagOrStoredDiag D = (Diagnostic *)nullptr);
1478be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek
1488be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek  void emitStoredDiagnostic(StoredDiagnostic &Diag);
1498be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek};
1508be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek
1518be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek/// Subclass of DiagnosticRender that turns all subdiagostics into explicit
1528be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek/// notes.  It is up to subclasses to further define the behavior.
1538be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekclass DiagnosticNoteRenderer : public DiagnosticRenderer {
1548be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekpublic:
15516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  DiagnosticNoteRenderer(const LangOptions &LangOpts,
15602c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor                         DiagnosticOptions *DiagOpts)
15716afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis    : DiagnosticRenderer(LangOpts, DiagOpts) {}
1588be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek
1598be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek  virtual ~DiagnosticNoteRenderer();
160830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor
161651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
162651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                           const SourceManager &SM) override;
163651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
164651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
165651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                          StringRef ModuleName,
166651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                          const SourceManager &SM) override;
167651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
168651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
169651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                  StringRef ModuleName,
170651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                  const SourceManager &SM) override;
171830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor
17216afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  virtual void emitNote(SourceLocation Loc, StringRef Message,
17316afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                        const SourceManager *SM) = 0;
1742898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek};
1752898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} // end clang namespace
1762898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#endif
177