clang API Documentation
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