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_DIAGNOSTIC_RENDERER_H_
00017 #define LLVM_CLANG_FRONTEND_DIAGNOSTIC_RENDERER_H_
00018 
00019 #include "clang/Basic/Diagnostic.h"
00020 #include "clang/Basic/LLVM.h"
00021 #include "clang/Basic/SourceLocation.h"
00022 #include "llvm/ADT/PointerUnion.h"
00023 
00024 namespace clang {
00025 
00026 class DiagnosticOptions;
00027 class LangOptions;
00028 class SourceManager;
00029 
00030 typedef llvm::PointerUnion<const Diagnostic *,
00031                            const StoredDiagnostic *> DiagOrStoredDiag;
00032   
00033 /// \brief Class to encapsulate the logic for formatting a diagnostic message.
00034 ///  Actual "printing" logic is implemented by subclasses.
00035 ///
00036 /// This class provides an interface for building and emitting
00037 /// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt
00038 /// Hints, and code snippets. In the presence of macros this involves
00039 /// a recursive process, synthesizing notes for each macro expansion.
00040 ///
00041 /// A brief worklist:
00042 /// FIXME: Sink the recursive printing of template instantiations into this
00043 /// class.
00044 class DiagnosticRenderer {
00045 protected:
00046   const LangOptions &LangOpts;
00047   const DiagnosticOptions &DiagOpts;
00048   
00049   /// \brief The location of the previous diagnostic if known.
00050   ///
00051   /// This will be invalid in cases where there is no (known) previous
00052   /// diagnostic location, or that location itself is invalid or comes from
00053   /// a different source manager than SM.
00054   SourceLocation LastLoc;
00055   
00056   /// \brief The location of the last include whose stack was printed if known.
00057   ///
00058   /// Same restriction as \see LastLoc essentially, but tracking include stack
00059   /// root locations rather than diagnostic locations.
00060   SourceLocation LastIncludeLoc;
00061   
00062   /// \brief The level of the last diagnostic emitted.
00063   ///
00064   /// The level of the last diagnostic emitted. Used to detect level changes
00065   /// which change the amount of information displayed.
00066   DiagnosticsEngine::Level LastLevel;
00067 
00068   DiagnosticRenderer(const LangOptions &LangOpts,
00069                      const DiagnosticOptions &DiagOpts);
00070   
00071   virtual ~DiagnosticRenderer();
00072   
00073   virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc,
00074                                      DiagnosticsEngine::Level Level,
00075                                      StringRef Message,
00076                                      ArrayRef<CharSourceRange> Ranges,
00077                                      const SourceManager *SM,
00078                                      DiagOrStoredDiag Info) = 0;
00079   
00080   virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
00081                                  DiagnosticsEngine::Level Level,
00082                                  ArrayRef<CharSourceRange> Ranges,
00083                                  const SourceManager &SM) = 0;
00084   
00085   virtual void emitBasicNote(StringRef Message) = 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   
00096   virtual void beginDiagnostic(DiagOrStoredDiag D,
00097                                DiagnosticsEngine::Level Level) {}
00098   virtual void endDiagnostic(DiagOrStoredDiag D,
00099                              DiagnosticsEngine::Level Level) {}
00100 
00101   
00102 private:
00103   void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level,
00104                         const SourceManager &SM);
00105   void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM);
00106   void emitMacroExpansionsAndCarets(SourceLocation Loc,
00107                                     DiagnosticsEngine::Level Level,
00108                                     SmallVectorImpl<CharSourceRange>& Ranges,
00109                                     ArrayRef<FixItHint> Hints,
00110                                     const SourceManager &SM,
00111                                     unsigned &MacroDepth,
00112                                     unsigned OnMacroInst = 0);
00113 public:
00114   /// \brief Emit a diagnostic.
00115   ///
00116   /// This is the primary entry point for emitting diagnostic messages.
00117   /// It handles formatting and rendering the message as well as any ancillary
00118   /// information needed based on macros whose expansions impact the
00119   /// diagnostic.
00120   ///
00121   /// \param Loc The location for this caret.
00122   /// \param Level The level of the diagnostic to be emitted.
00123   /// \param Message The diagnostic message to emit.
00124   /// \param Ranges The underlined ranges for this code snippet.
00125   /// \param FixItHints The FixIt hints active for this diagnostic.
00126   /// \param SM The SourceManager; will be null if the diagnostic came from the
00127   ///        frontend, thus \param Loc will be invalid.
00128   void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level,
00129                       StringRef Message, ArrayRef<CharSourceRange> Ranges,
00130                       ArrayRef<FixItHint> FixItHints,
00131                       const SourceManager *SM,
00132                       DiagOrStoredDiag D = (Diagnostic *)0);
00133 
00134   void emitStoredDiagnostic(StoredDiagnostic &Diag);
00135 };
00136   
00137 /// Subclass of DiagnosticRender that turns all subdiagostics into explicit
00138 /// notes.  It is up to subclasses to further define the behavior.
00139 class DiagnosticNoteRenderer : public DiagnosticRenderer {
00140 public:
00141   DiagnosticNoteRenderer(const LangOptions &LangOpts,
00142                          const DiagnosticOptions &DiagOpts)
00143     : DiagnosticRenderer(LangOpts, DiagOpts) {}
00144   
00145   virtual ~DiagnosticNoteRenderer();
00146   
00147   virtual void emitBasicNote(StringRef Message);
00148     
00149   virtual void emitIncludeLocation(SourceLocation Loc,
00150                                    PresumedLoc PLoc,
00151                                    const SourceManager &SM);
00152   
00153   virtual void emitNote(SourceLocation Loc, StringRef Message,
00154                         const SourceManager *SM) = 0;
00155 };
00156 } // end clang namespace
00157 #endif