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/Optional.h"
     23 #include "llvm/ADT/PointerUnion.h"
     24 
     25 namespace clang {
     26 
     27 class DiagnosticOptions;
     28 class LangOptions;
     29 class SourceManager;
     30 
     31 typedef llvm::PointerUnion<const Diagnostic *,
     32                            const StoredDiagnostic *> DiagOrStoredDiag;
     33 
     34 /// \brief Class to encapsulate the logic for formatting a diagnostic message.
     35 ///
     36 /// Actual "printing" logic is implemented by subclasses.
     37 ///
     38 /// This class provides an interface for building and emitting
     39 /// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt
     40 /// Hints, and code snippets. In the presence of macros this involves
     41 /// a recursive process, synthesizing notes for each macro expansion.
     42 ///
     43 /// A brief worklist:
     44 /// FIXME: Sink the recursive printing of template instantiations into this
     45 /// class.
     46 class DiagnosticRenderer {
     47 protected:
     48   const LangOptions &LangOpts;
     49   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
     50 
     51   /// \brief The location of the previous diagnostic if known.
     52   ///
     53   /// This will be invalid in cases where there is no (known) previous
     54   /// diagnostic location, or that location itself is invalid or comes from
     55   /// a different source manager than SM.
     56   SourceLocation LastLoc;
     57 
     58   /// \brief The location of the last include whose stack was printed if known.
     59   ///
     60   /// Same restriction as LastLoc essentially, but tracking include stack
     61   /// root locations rather than diagnostic locations.
     62   SourceLocation LastIncludeLoc;
     63 
     64   /// \brief The level of the last diagnostic emitted.
     65   ///
     66   /// The level of the last diagnostic emitted. Used to detect level changes
     67   /// which change the amount of information displayed.
     68   DiagnosticsEngine::Level LastLevel;
     69 
     70   DiagnosticRenderer(const LangOptions &LangOpts,
     71                      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                                      const SourceManager *SM,
     80                                      DiagOrStoredDiag Info) = 0;
     81 
     82   virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
     83                                  DiagnosticsEngine::Level Level,
     84                                  ArrayRef<CharSourceRange> Ranges,
     85                                  const SourceManager &SM) = 0;
     86 
     87   virtual void emitBasicNote(StringRef Message) = 0;
     88 
     89   virtual void emitCodeContext(SourceLocation Loc,
     90                                DiagnosticsEngine::Level Level,
     91                                SmallVectorImpl<CharSourceRange>& Ranges,
     92                                ArrayRef<FixItHint> Hints,
     93                                const SourceManager &SM) = 0;
     94 
     95   virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
     96                                    const SourceManager &SM) = 0;
     97   virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
     98                                   StringRef ModuleName,
     99                                   const SourceManager &SM) = 0;
    100   virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
    101                                           StringRef ModuleName,
    102                                           const SourceManager &SM) = 0;
    103 
    104   virtual void beginDiagnostic(DiagOrStoredDiag D,
    105                                DiagnosticsEngine::Level Level) {}
    106   virtual void endDiagnostic(DiagOrStoredDiag D,
    107                              DiagnosticsEngine::Level Level) {}
    108 
    109 
    110 private:
    111   void emitIncludeStack(SourceLocation Loc, PresumedLoc PLoc,
    112                         DiagnosticsEngine::Level Level, const SourceManager &SM);
    113   void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM);
    114   void emitImportStack(SourceLocation Loc, const SourceManager &SM);
    115   void emitImportStackRecursively(SourceLocation Loc, StringRef ModuleName,
    116                                   const SourceManager &SM);
    117   void emitModuleBuildStack(const SourceManager &SM);
    118   void emitCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
    119                  ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints,
    120                  const SourceManager &SM);
    121   void emitMacroExpansions(SourceLocation Loc,
    122                            DiagnosticsEngine::Level Level,
    123                            ArrayRef<CharSourceRange> Ranges,
    124                            ArrayRef<FixItHint> Hints,
    125                            const SourceManager &SM,
    126                            unsigned &MacroDepth,
    127                            unsigned OnMacroInst = 0);
    128 public:
    129   /// \brief Emit a diagnostic.
    130   ///
    131   /// This is the primary entry point for emitting diagnostic messages.
    132   /// It handles formatting and rendering the message as well as any ancillary
    133   /// information needed based on macros whose expansions impact the
    134   /// diagnostic.
    135   ///
    136   /// \param Loc The location for this caret.
    137   /// \param Level The level of the diagnostic to be emitted.
    138   /// \param Message The diagnostic message to emit.
    139   /// \param Ranges The underlined ranges for this code snippet.
    140   /// \param FixItHints The FixIt hints active for this diagnostic.
    141   /// \param SM The SourceManager; will be null if the diagnostic came from the
    142   ///        frontend, thus \p Loc will be invalid.
    143   void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level,
    144                       StringRef Message, ArrayRef<CharSourceRange> Ranges,
    145                       ArrayRef<FixItHint> FixItHints,
    146                       const SourceManager *SM,
    147                       DiagOrStoredDiag D = (Diagnostic *)0);
    148 
    149   void emitStoredDiagnostic(StoredDiagnostic &Diag);
    150 };
    151 
    152 /// Subclass of DiagnosticRender that turns all subdiagostics into explicit
    153 /// notes.  It is up to subclasses to further define the behavior.
    154 class DiagnosticNoteRenderer : public DiagnosticRenderer {
    155 public:
    156   DiagnosticNoteRenderer(const LangOptions &LangOpts,
    157                          DiagnosticOptions *DiagOpts)
    158     : DiagnosticRenderer(LangOpts, DiagOpts) {}
    159 
    160   virtual ~DiagnosticNoteRenderer();
    161 
    162   virtual void emitBasicNote(StringRef Message);
    163 
    164   virtual void emitIncludeLocation(SourceLocation Loc,
    165                                    PresumedLoc PLoc,
    166                                    const SourceManager &SM);
    167 
    168   virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
    169                                   StringRef ModuleName,
    170                                   const SourceManager &SM);
    171 
    172   virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
    173                                           StringRef ModuleName,
    174                                           const SourceManager &SM);
    175 
    176   virtual void emitNote(SourceLocation Loc, StringRef Message,
    177                         const SourceManager *SM) = 0;
    178 };
    179 } // end clang namespace
    180 #endif
    181