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"
228be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek#include "llvm/ADT/PointerUnion.h"
232898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
242898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremeneknamespace clang {
252898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
268be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekclass DiagnosticOptions;
278be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekclass LangOptions;
288be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekclass SourceManager;
298be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek
308be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenektypedef llvm::PointerUnion<const Diagnostic *,
318be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek                           const StoredDiagnostic *> DiagOrStoredDiag;
328be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek
332898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \brief Class to encapsulate the logic for formatting a diagnostic message.
342898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek///  Actual "printing" logic is implemented by subclasses.
352898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek///
362898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// This class provides an interface for building and emitting
372898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt
382898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// Hints, and code snippets. In the presence of macros this involves
392898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// a recursive process, synthesizing notes for each macro expansion.
402898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek///
412898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// A brief worklist:
422898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// FIXME: Sink the recursive printing of template instantiations into this
432898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// class.
442898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekclass DiagnosticRenderer {
452898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekprotected:
462898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  const SourceManager &SM;
472898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  const LangOptions &LangOpts;
482898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  const DiagnosticOptions &DiagOpts;
492898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
502898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \brief The location of the previous diagnostic if known.
512898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  ///
522898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// This will be invalid in cases where there is no (known) previous
532898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// diagnostic location, or that location itself is invalid or comes from
542898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// a different source manager than SM.
552898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  SourceLocation LastLoc;
562898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
572898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \brief The location of the last include whose stack was printed if known.
582898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  ///
592898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// Same restriction as \see LastLoc essentially, but tracking include stack
602898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// root locations rather than diagnostic locations.
612898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  SourceLocation LastIncludeLoc;
622898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
632898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \brief The level of the last diagnostic emitted.
642898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  ///
652898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// The level of the last diagnostic emitted. Used to detect level changes
662898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// which change the amount of information displayed.
672898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  DiagnosticsEngine::Level LastLevel;
682898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
692898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  DiagnosticRenderer(const SourceManager &SM,
702898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                     const LangOptions &LangOpts,
712898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                     const 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,
798be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek                                     DiagOrStoredDiag Info) = 0;
802898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
812898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
822898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                 DiagnosticsEngine::Level Level,
832898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                 ArrayRef<CharSourceRange> Ranges) = 0;
842898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
852898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  virtual void emitBasicNote(StringRef Message) = 0;
862898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
872898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  virtual void emitCodeContext(SourceLocation Loc,
882898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                               DiagnosticsEngine::Level Level,
892898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                               SmallVectorImpl<CharSourceRange>& Ranges,
902898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                               ArrayRef<FixItHint> Hints) = 0;
912898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
922898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc) = 0;
932898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
948be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek  virtual void beginDiagnostic(DiagOrStoredDiag D,
952898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                               DiagnosticsEngine::Level Level) {}
968be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek  virtual void endDiagnostic(DiagOrStoredDiag D,
972898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                             DiagnosticsEngine::Level Level) {}
982898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
992898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
1002898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekprivate:
1012898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level);
1022898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  void emitIncludeStackRecursively(SourceLocation Loc);
1032898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  void emitMacroExpansionsAndCarets(SourceLocation Loc,
1042898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                    DiagnosticsEngine::Level Level,
1052898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                    SmallVectorImpl<CharSourceRange>& Ranges,
1062898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                    ArrayRef<FixItHint> Hints,
1072898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                    unsigned &MacroDepth,
1082898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                    unsigned OnMacroInst = 0);
1092898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekpublic:
1102898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \brief Emit a diagnostic.
1112898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  ///
1122898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// This is the primary entry point for emitting diagnostic messages.
1132898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// It handles formatting and rendering the message as well as any ancillary
1142898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// information needed based on macros whose expansions impact the
1152898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// diagnostic.
1162898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  ///
1172898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \param Loc The location for this caret.
1182898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \param Level The level of the diagnostic to be emitted.
1192898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \param Message The diagnostic message to emit.
1202898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \param Ranges The underlined ranges for this code snippet.
1212898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  /// \param FixItHints The FixIt hints active for this diagnostic.
1222898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level,
1232898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                      StringRef Message, ArrayRef<CharSourceRange> Ranges,
1242898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                      ArrayRef<FixItHint> FixItHints,
1258be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek                      DiagOrStoredDiag D = (Diagnostic *)0);
1268be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek
1278be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek  void emitStoredDiagnostic(StoredDiagnostic &Diag);
1288be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek};
1298be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek
1308be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek/// Subclass of DiagnosticRender that turns all subdiagostics into explicit
1318be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek/// notes.  It is up to subclasses to further define the behavior.
1328be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekclass DiagnosticNoteRenderer : public DiagnosticRenderer {
1338be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekpublic:
1348be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek  DiagnosticNoteRenderer(const SourceManager &SM,
1358be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek                         const LangOptions &LangOpts,
1368be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek                         const DiagnosticOptions &DiagOpts)
1378be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek    : DiagnosticRenderer(SM, LangOpts, DiagOpts) {}
1388be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek
1398be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek  virtual ~DiagnosticNoteRenderer();
1408be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek
1418be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek  virtual void emitBasicNote(StringRef Message);
1428be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek
1438be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek  virtual void emitIncludeLocation(SourceLocation Loc,
1448be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek                                   PresumedLoc PLoc);
1458be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek
1468be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek  virtual void emitNote(SourceLocation Loc, StringRef Message) = 0;
1472898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek};
1482898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} // end clang namespace
1492898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#endif
150