Home | History | Annotate | Download | only in Frontend
      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 
     24 namespace clang {
     25 
     26 class DiagnosticOptions;
     27 class LangOptions;
     28 class SourceManager;
     29 
     30 typedef 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.
     44 class DiagnosticRenderer {
     45 protected:
     46   const SourceManager &SM;
     47   const LangOptions &LangOpts;
     48   const DiagnosticOptions &DiagOpts;
     49 
     50   /// \brief The location of the previous diagnostic if known.
     51   ///
     52   /// This will be invalid in cases where there is no (known) previous
     53   /// diagnostic location, or that location itself is invalid or comes from
     54   /// a different source manager than SM.
     55   SourceLocation LastLoc;
     56 
     57   /// \brief The location of the last include whose stack was printed if known.
     58   ///
     59   /// Same restriction as \see LastLoc essentially, but tracking include stack
     60   /// root locations rather than diagnostic locations.
     61   SourceLocation LastIncludeLoc;
     62 
     63   /// \brief The level of the last diagnostic emitted.
     64   ///
     65   /// The level of the last diagnostic emitted. Used to detect level changes
     66   /// which change the amount of information displayed.
     67   DiagnosticsEngine::Level LastLevel;
     68 
     69   DiagnosticRenderer(const SourceManager &SM,
     70                      const LangOptions &LangOpts,
     71                      const DiagnosticOptions &DiagOpts);
     72 
     73   virtual ~DiagnosticRenderer();
     74 
     75   virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
     76                                      DiagnosticsEngine::Level Level,
     77                                      StringRef Message,
     78                                      ArrayRef<CharSourceRange> Ranges,
     79                                      DiagOrStoredDiag Info) = 0;
     80 
     81   virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
     82                                  DiagnosticsEngine::Level Level,
     83                                  ArrayRef<CharSourceRange> Ranges) = 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) = 0;
     91 
     92   virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc) = 0;
     93 
     94   virtual void beginDiagnostic(DiagOrStoredDiag D,
     95                                DiagnosticsEngine::Level Level) {}
     96   virtual void endDiagnostic(DiagOrStoredDiag D,
     97                              DiagnosticsEngine::Level Level) {}
     98 
     99 
    100 private:
    101   void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level);
    102   void emitIncludeStackRecursively(SourceLocation Loc);
    103   void emitMacroExpansionsAndCarets(SourceLocation Loc,
    104                                     DiagnosticsEngine::Level Level,
    105                                     SmallVectorImpl<CharSourceRange>& Ranges,
    106                                     ArrayRef<FixItHint> Hints,
    107                                     unsigned &MacroDepth,
    108                                     unsigned OnMacroInst = 0);
    109 public:
    110   /// \brief Emit a diagnostic.
    111   ///
    112   /// This is the primary entry point for emitting diagnostic messages.
    113   /// It handles formatting and rendering the message as well as any ancillary
    114   /// information needed based on macros whose expansions impact the
    115   /// diagnostic.
    116   ///
    117   /// \param Loc The location for this caret.
    118   /// \param Level The level of the diagnostic to be emitted.
    119   /// \param Message The diagnostic message to emit.
    120   /// \param Ranges The underlined ranges for this code snippet.
    121   /// \param FixItHints The FixIt hints active for this diagnostic.
    122   void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level,
    123                       StringRef Message, ArrayRef<CharSourceRange> Ranges,
    124                       ArrayRef<FixItHint> FixItHints,
    125                       DiagOrStoredDiag D = (Diagnostic *)0);
    126 
    127   void emitStoredDiagnostic(StoredDiagnostic &Diag);
    128 };
    129 
    130 /// Subclass of DiagnosticRender that turns all subdiagostics into explicit
    131 /// notes.  It is up to subclasses to further define the behavior.
    132 class DiagnosticNoteRenderer : public DiagnosticRenderer {
    133 public:
    134   DiagnosticNoteRenderer(const SourceManager &SM,
    135                          const LangOptions &LangOpts,
    136                          const DiagnosticOptions &DiagOpts)
    137     : DiagnosticRenderer(SM, LangOpts, DiagOpts) {}
    138 
    139   virtual ~DiagnosticNoteRenderer();
    140 
    141   virtual void emitBasicNote(StringRef Message);
    142 
    143   virtual void emitIncludeLocation(SourceLocation Loc,
    144                                    PresumedLoc PLoc);
    145 
    146   virtual void emitNote(SourceLocation Loc, StringRef Message) = 0;
    147 };
    148 } // end clang namespace
    149 #endif
    150