clang API Documentation

DiagnosticRenderer.h
Go to the documentation of this file.
00001 //===--- DiagnosticRenderer.h - Diagnostic Pretty-Printing ------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This is a utility class that provides support for pretty-printing of
00011 // diagnostics. It is used to implement the different code paths which require
00012 // such functionality in a consistent way.
00013 //
00014 //===----------------------------------------------------------------------===//
00015 
00016 #ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
00017 #define LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
00018 
00019 #include "clang/Basic/Diagnostic.h"
00020 #include "clang/Basic/LLVM.h"
00021 #include "clang/Basic/SourceLocation.h"
00022 #include "llvm/ADT/Optional.h"
00023 #include "llvm/ADT/PointerUnion.h"
00024 
00025 namespace clang {
00026 
00027 class DiagnosticOptions;
00028 class LangOptions;
00029 class SourceManager;
00030 
00031 typedef llvm::PointerUnion<const Diagnostic *,
00032                            const StoredDiagnostic *> DiagOrStoredDiag;
00033   
00034 /// \brief Class to encapsulate the logic for formatting a diagnostic message.
00035 ///
00036 /// Actual "printing" logic is implemented by subclasses.
00037 ///
00038 /// This class provides an interface for building and emitting
00039 /// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt
00040 /// Hints, and code snippets. In the presence of macros this involves
00041 /// a recursive process, synthesizing notes for each macro expansion.
00042 ///
00043 /// A brief worklist:
00044 /// FIXME: Sink the recursive printing of template instantiations into this
00045 /// class.
00046 class DiagnosticRenderer {
00047 protected:
00048   const LangOptions &LangOpts;
00049   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
00050   
00051   /// \brief The location of the previous diagnostic if known.
00052   ///
00053   /// This will be invalid in cases where there is no (known) previous
00054   /// diagnostic location, or that location itself is invalid or comes from
00055   /// a different source manager than SM.
00056   SourceLocation LastLoc;
00057   
00058   /// \brief The location of the last include whose stack was printed if known.
00059   ///
00060   /// Same restriction as LastLoc essentially, but tracking include stack
00061   /// root locations rather than diagnostic locations.
00062   SourceLocation LastIncludeLoc;
00063   
00064   /// \brief The level of the last diagnostic emitted.
00065   ///
00066   /// The level of the last diagnostic emitted. Used to detect level changes
00067   /// which change the amount of information displayed.
00068   DiagnosticsEngine::Level LastLevel;
00069 
00070   DiagnosticRenderer(const LangOptions &LangOpts,
00071                      DiagnosticOptions *DiagOpts);
00072   
00073   virtual ~DiagnosticRenderer();
00074   
00075   virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
00076                                      DiagnosticsEngine::Level Level,
00077                                      StringRef Message,
00078                                      ArrayRef<CharSourceRange> Ranges,
00079                                      const SourceManager *SM,
00080                                      DiagOrStoredDiag Info) = 0;
00081   
00082   virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
00083                                  DiagnosticsEngine::Level Level,
00084                                  ArrayRef<CharSourceRange> Ranges,
00085                                  const SourceManager &SM) = 0;
00086 
00087   virtual void emitCodeContext(SourceLocation Loc,
00088                                DiagnosticsEngine::Level Level,
00089                                SmallVectorImpl<CharSourceRange>& Ranges,
00090                                ArrayRef<FixItHint> Hints,
00091                                const SourceManager &SM) = 0;
00092   
00093   virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
00094                                    const SourceManager &SM) = 0;
00095   virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
00096                                   StringRef ModuleName,
00097                                   const SourceManager &SM) = 0;
00098   virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
00099                                           StringRef ModuleName,
00100                                           const SourceManager &SM) = 0;
00101 
00102   virtual void beginDiagnostic(DiagOrStoredDiag D,
00103                                DiagnosticsEngine::Level Level) {}
00104   virtual void endDiagnostic(DiagOrStoredDiag D,
00105                              DiagnosticsEngine::Level Level) {}
00106 
00107   
00108 private:
00109   void emitBasicNote(StringRef Message);
00110   void emitIncludeStack(SourceLocation Loc, PresumedLoc PLoc,
00111                         DiagnosticsEngine::Level Level, const SourceManager &SM);
00112   void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM);
00113   void emitImportStack(SourceLocation Loc, const SourceManager &SM);
00114   void emitImportStackRecursively(SourceLocation Loc, StringRef ModuleName,
00115                                   const SourceManager &SM);
00116   void emitModuleBuildStack(const SourceManager &SM);
00117   void emitCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
00118                  ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints,
00119                  const SourceManager &SM);
00120   void emitMacroExpansions(SourceLocation Loc,
00121                            DiagnosticsEngine::Level Level,
00122                            ArrayRef<CharSourceRange> Ranges,
00123                            ArrayRef<FixItHint> Hints,
00124                            const SourceManager &SM,
00125                            unsigned &MacroDepth,
00126                            unsigned OnMacroInst = 0);
00127 public:
00128   /// \brief Emit a diagnostic.
00129   ///
00130   /// This is the primary entry point for emitting diagnostic messages.
00131   /// It handles formatting and rendering the message as well as any ancillary
00132   /// information needed based on macros whose expansions impact the
00133   /// diagnostic.
00134   ///
00135   /// \param Loc The location for this caret.
00136   /// \param Level The level of the diagnostic to be emitted.
00137   /// \param Message The diagnostic message to emit.
00138   /// \param Ranges The underlined ranges for this code snippet.
00139   /// \param FixItHints The FixIt hints active for this diagnostic.
00140   /// \param SM The SourceManager; will be null if the diagnostic came from the
00141   ///        frontend, thus \p Loc will be invalid.
00142   void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level,
00143                       StringRef Message, ArrayRef<CharSourceRange> Ranges,
00144                       ArrayRef<FixItHint> FixItHints,
00145                       const SourceManager *SM,
00146                       DiagOrStoredDiag D = (Diagnostic *)nullptr);
00147 
00148   void emitStoredDiagnostic(StoredDiagnostic &Diag);
00149 };
00150   
00151 /// Subclass of DiagnosticRender that turns all subdiagostics into explicit
00152 /// notes.  It is up to subclasses to further define the behavior.
00153 class DiagnosticNoteRenderer : public DiagnosticRenderer {
00154 public:
00155   DiagnosticNoteRenderer(const LangOptions &LangOpts,
00156                          DiagnosticOptions *DiagOpts)
00157     : DiagnosticRenderer(LangOpts, DiagOpts) {}
00158   
00159   virtual ~DiagnosticNoteRenderer();
00160 
00161   void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
00162                            const SourceManager &SM) override;
00163 
00164   void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
00165                           StringRef ModuleName,
00166                           const SourceManager &SM) override;
00167 
00168   void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
00169                                   StringRef ModuleName,
00170                                   const SourceManager &SM) override;
00171 
00172   virtual void emitNote(SourceLocation Loc, StringRef Message,
00173                         const SourceManager *SM) = 0;
00174 };
00175 } // end clang namespace
00176 #endif