12898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek//===--- DiagnosticRenderer.h - Diagnostic Pretty-Printing ------*- C++ -*-===// 22898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// 32898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// The LLVM Compiler Infrastructure 42898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// 52898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// This file is distributed under the University of Illinois Open Source 62898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// License. See LICENSE.TXT for details. 72898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// 82898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek//===----------------------------------------------------------------------===// 92898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// 102898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// This is a utility class that provides support for pretty-printing of 112898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// diagnostics. It is used to implement the different code paths which require 122898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// such functionality in a consistent way. 132898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek// 142898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek//===----------------------------------------------------------------------===// 152898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 162898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTIC_RENDERER_H_ 172898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#define LLVM_CLANG_FRONTEND_DIAGNOSTIC_RENDERER_H_ 182898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 192898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "clang/Basic/Diagnostic.h" 202898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "clang/Basic/LLVM.h" 212898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#include "clang/Basic/SourceLocation.h" 226c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor#include "llvm/ADT/Optional.h" 238be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek#include "llvm/ADT/PointerUnion.h" 242898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 252898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremeneknamespace clang { 262898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 278be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekclass DiagnosticOptions; 288be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekclass LangOptions; 298be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekclass SourceManager; 308be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 318be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenektypedef llvm::PointerUnion<const Diagnostic *, 328be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek const StoredDiagnostic *> DiagOrStoredDiag; 338be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 342898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// \brief Class to encapsulate the logic for formatting a diagnostic message. 35c34464ee3367de42c477561c0ae069675be8393cJames Dennett/// 36c34464ee3367de42c477561c0ae069675be8393cJames Dennett/// Actual "printing" logic is implemented by subclasses. 372898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 382898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// This class provides an interface for building and emitting 392898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt 402898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// Hints, and code snippets. In the presence of macros this involves 412898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// a recursive process, synthesizing notes for each macro expansion. 422898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// 432898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// A brief worklist: 442898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// FIXME: Sink the recursive printing of template instantiations into this 452898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek/// class. 462898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekclass DiagnosticRenderer { 472898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekprotected: 482898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek const LangOptions &LangOpts; 4902c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; 502898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 512898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// \brief The location of the previous diagnostic if known. 522898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// 532898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// This will be invalid in cases where there is no (known) previous 542898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// diagnostic location, or that location itself is invalid or comes from 552898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// a different source manager than SM. 562898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SourceLocation LastLoc; 572898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 582898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// \brief The location of the last include whose stack was printed if known. 592898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// 60c34464ee3367de42c477561c0ae069675be8393cJames Dennett /// Same restriction as LastLoc essentially, but tracking include stack 612898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// root locations rather than diagnostic locations. 622898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SourceLocation LastIncludeLoc; 632898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 642898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// \brief The level of the last diagnostic emitted. 652898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// 662898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// The level of the last diagnostic emitted. Used to detect level changes 672898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// which change the amount of information displayed. 682898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek DiagnosticsEngine::Level LastLevel; 692898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 7016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis DiagnosticRenderer(const LangOptions &LangOpts, 7102c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor DiagnosticOptions *DiagOpts); 722898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 732898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek virtual ~DiagnosticRenderer(); 742898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 752898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek virtual void emitDiagnosticMessage(SourceLocation Loc, PresumedLoc PLoc, 762898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek DiagnosticsEngine::Level Level, 772898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek StringRef Message, 782898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek ArrayRef<CharSourceRange> Ranges, 7916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager *SM, 808be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek DiagOrStoredDiag Info) = 0; 812898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 822898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, 832898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek DiagnosticsEngine::Level Level, 8416afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis ArrayRef<CharSourceRange> Ranges, 8516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager &SM) = 0; 86ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 872898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek virtual void emitCodeContext(SourceLocation Loc, 882898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek DiagnosticsEngine::Level Level, 892898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek SmallVectorImpl<CharSourceRange>& Ranges, 9016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis ArrayRef<FixItHint> Hints, 9116afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager &SM) = 0; 922898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 9316afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, 9416afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager &SM) = 0; 956c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, 966c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor StringRef ModuleName, 976c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor const SourceManager &SM) = 0; 98830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, 99830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor StringRef ModuleName, 100830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor const SourceManager &SM) = 0; 101830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor 1028be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek virtual void beginDiagnostic(DiagOrStoredDiag D, 1032898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek DiagnosticsEngine::Level Level) {} 1048be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek virtual void endDiagnostic(DiagOrStoredDiag D, 1052898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek DiagnosticsEngine::Level Level) {} 1062898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1072898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 1082898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekprivate: 109ef8225444452a1486bd721f3285301fe84643b00Stephen Hines void emitBasicNote(StringRef Message); 1106c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor void emitIncludeStack(SourceLocation Loc, PresumedLoc PLoc, 1116c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor DiagnosticsEngine::Level Level, const SourceManager &SM); 11216afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM); 1136c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor void emitImportStack(SourceLocation Loc, const SourceManager &SM); 1146c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor void emitImportStackRecursively(SourceLocation Loc, StringRef ModuleName, 1156c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor const SourceManager &SM); 1164565e487531c7bf6d348dbe9f5529784966fc7aeDouglas Gregor void emitModuleBuildStack(const SourceManager &SM); 117ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith void emitCaret(SourceLocation Loc, DiagnosticsEngine::Level Level, 118ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints, 119ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith const SourceManager &SM); 120ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith void emitMacroExpansions(SourceLocation Loc, 121ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith DiagnosticsEngine::Level Level, 122ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith ArrayRef<CharSourceRange> Ranges, 123ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith ArrayRef<FixItHint> Hints, 124ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith const SourceManager &SM, 125ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith unsigned &MacroDepth, 126ac31c8346f1ce3628b5a7fb862fefab5b94f8e82Richard Smith unsigned OnMacroInst = 0); 1272898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekpublic: 1282898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// \brief Emit a diagnostic. 1292898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// 1302898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// This is the primary entry point for emitting diagnostic messages. 1312898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// It handles formatting and rendering the message as well as any ancillary 1322898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// information needed based on macros whose expansions impact the 1332898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// diagnostic. 1342898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// 1352898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// \param Loc The location for this caret. 1362898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// \param Level The level of the diagnostic to be emitted. 1372898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// \param Message The diagnostic message to emit. 1382898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// \param Ranges The underlined ranges for this code snippet. 1392898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek /// \param FixItHints The FixIt hints active for this diagnostic. 14016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis /// \param SM The SourceManager; will be null if the diagnostic came from the 14170517ca5c07c4b41ff8662b94ee22047b0299f8cDmitri Gribenko /// frontend, thus \p Loc will be invalid. 1422898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level, 1432898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek StringRef Message, ArrayRef<CharSourceRange> Ranges, 1442898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek ArrayRef<FixItHint> FixItHints, 14516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager *SM, 1466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines DiagOrStoredDiag D = (Diagnostic *)nullptr); 1478be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 1488be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek void emitStoredDiagnostic(StoredDiagnostic &Diag); 1498be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek}; 1508be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 1518be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek/// Subclass of DiagnosticRender that turns all subdiagostics into explicit 1528be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek/// notes. It is up to subclasses to further define the behavior. 1538be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekclass DiagnosticNoteRenderer : public DiagnosticRenderer { 1548be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenekpublic: 15516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis DiagnosticNoteRenderer(const LangOptions &LangOpts, 15602c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor DiagnosticOptions *DiagOpts) 15716afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis : DiagnosticRenderer(LangOpts, DiagOpts) {} 1588be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek 1598be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek virtual ~DiagnosticNoteRenderer(); 160830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor 161651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc, 162651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const SourceManager &SM) override; 163651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 164651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, 165651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef ModuleName, 166651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const SourceManager &SM) override; 167651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 168651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc, 169651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef ModuleName, 170651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const SourceManager &SM) override; 171830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor 17216afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis virtual void emitNote(SourceLocation Loc, StringRef Message, 17316afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager *SM) = 0; 1742898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek}; 1752898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek} // end clang namespace 1762898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek#endif 177