Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:55

0001 //===- DiagnosticRenderer.h - Diagnostic Pretty-Printing --------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This is a utility class that provides support for pretty-printing of
0010 // diagnostics. It is used to implement the different code paths which require
0011 // such functionality in a consistent way.
0012 //
0013 //===----------------------------------------------------------------------===//
0014 
0015 #ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
0016 #define LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H
0017 
0018 #include "clang/Basic/Diagnostic.h"
0019 #include "clang/Basic/DiagnosticOptions.h"
0020 #include "clang/Basic/LLVM.h"
0021 #include "clang/Basic/SourceLocation.h"
0022 #include "llvm/ADT/ArrayRef.h"
0023 #include "llvm/ADT/IntrusiveRefCntPtr.h"
0024 #include "llvm/ADT/PointerUnion.h"
0025 #include "llvm/ADT/StringRef.h"
0026 
0027 namespace clang {
0028 
0029 class LangOptions;
0030 class SourceManager;
0031 
0032 using DiagOrStoredDiag =
0033     llvm::PointerUnion<const Diagnostic *, const StoredDiagnostic *>;
0034 
0035 /// Class to encapsulate the logic for formatting a diagnostic message.
0036 ///
0037 /// Actual "printing" logic is implemented by subclasses.
0038 ///
0039 /// This class provides an interface for building and emitting
0040 /// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt
0041 /// Hints, and code snippets. In the presence of macros this involves
0042 /// a recursive process, synthesizing notes for each macro expansion.
0043 ///
0044 /// A brief worklist:
0045 /// FIXME: Sink the recursive printing of template instantiations into this
0046 /// class.
0047 class DiagnosticRenderer {
0048 protected:
0049   const LangOptions &LangOpts;
0050   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
0051 
0052   /// The location of the previous diagnostic if known.
0053   ///
0054   /// This will be invalid in cases where there is no (known) previous
0055   /// diagnostic location, or that location itself is invalid or comes from
0056   /// a different source manager than SM.
0057   SourceLocation LastLoc;
0058 
0059   /// The location of the last include whose stack was printed if known.
0060   ///
0061   /// Same restriction as LastLoc essentially, but tracking include stack
0062   /// root locations rather than diagnostic locations.
0063   SourceLocation LastIncludeLoc;
0064 
0065   /// The level of the last diagnostic emitted.
0066   ///
0067   /// The level of the last diagnostic emitted. Used to detect level changes
0068   /// which change the amount of information displayed.
0069   DiagnosticsEngine::Level LastLevel = DiagnosticsEngine::Ignored;
0070 
0071   DiagnosticRenderer(const LangOptions &LangOpts,
0072                      DiagnosticOptions *DiagOpts);
0073 
0074   virtual ~DiagnosticRenderer();
0075 
0076   virtual void emitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc,
0077                                      DiagnosticsEngine::Level Level,
0078                                      StringRef Message,
0079                                      ArrayRef<CharSourceRange> Ranges,
0080                                      DiagOrStoredDiag Info) = 0;
0081 
0082   virtual void emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
0083                                  DiagnosticsEngine::Level Level,
0084                                  ArrayRef<CharSourceRange> Ranges) = 0;
0085 
0086   virtual void emitCodeContext(FullSourceLoc Loc,
0087                                DiagnosticsEngine::Level Level,
0088                                SmallVectorImpl<CharSourceRange> &Ranges,
0089                                ArrayRef<FixItHint> Hints) = 0;
0090 
0091   virtual void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) = 0;
0092   virtual void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc,
0093                                   StringRef ModuleName) = 0;
0094   virtual void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc,
0095                                           StringRef ModuleName) = 0;
0096 
0097   virtual void beginDiagnostic(DiagOrStoredDiag D,
0098                                DiagnosticsEngine::Level Level) {}
0099   virtual void endDiagnostic(DiagOrStoredDiag D,
0100                              DiagnosticsEngine::Level Level) {}
0101 
0102 private:
0103   void emitBasicNote(StringRef Message);
0104   void emitIncludeStack(FullSourceLoc Loc, PresumedLoc PLoc,
0105                         DiagnosticsEngine::Level Level);
0106   void emitIncludeStackRecursively(FullSourceLoc Loc);
0107   void emitImportStack(FullSourceLoc Loc);
0108   void emitImportStackRecursively(FullSourceLoc Loc, StringRef ModuleName);
0109   void emitModuleBuildStack(const SourceManager &SM);
0110   void emitCaret(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
0111                  ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints);
0112   void emitSingleMacroExpansion(FullSourceLoc Loc,
0113                                 DiagnosticsEngine::Level Level,
0114                                 ArrayRef<CharSourceRange> Ranges);
0115   void emitMacroExpansions(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
0116                            ArrayRef<CharSourceRange> Ranges,
0117                            ArrayRef<FixItHint> Hints);
0118 
0119 public:
0120   /// Emit a diagnostic.
0121   ///
0122   /// This is the primary entry point for emitting diagnostic messages.
0123   /// It handles formatting and rendering the message as well as any ancillary
0124   /// information needed based on macros whose expansions impact the
0125   /// diagnostic.
0126   ///
0127   /// \param Loc The location for this caret.
0128   /// \param Level The level of the diagnostic to be emitted.
0129   /// \param Message The diagnostic message to emit.
0130   /// \param Ranges The underlined ranges for this code snippet.
0131   /// \param FixItHints The FixIt hints active for this diagnostic.
0132   void emitDiagnostic(FullSourceLoc Loc, DiagnosticsEngine::Level Level,
0133                       StringRef Message, ArrayRef<CharSourceRange> Ranges,
0134                       ArrayRef<FixItHint> FixItHints,
0135                       DiagOrStoredDiag D = (Diagnostic *)nullptr);
0136 
0137   void emitStoredDiagnostic(StoredDiagnostic &Diag);
0138 };
0139 
0140 /// Subclass of DiagnosticRender that turns all subdiagostics into explicit
0141 /// notes.  It is up to subclasses to further define the behavior.
0142 class DiagnosticNoteRenderer : public DiagnosticRenderer {
0143 public:
0144   DiagnosticNoteRenderer(const LangOptions &LangOpts,
0145                          DiagnosticOptions *DiagOpts)
0146       : DiagnosticRenderer(LangOpts, DiagOpts) {}
0147 
0148   ~DiagnosticNoteRenderer() override;
0149 
0150   void emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) override;
0151 
0152   void emitImportLocation(FullSourceLoc Loc, PresumedLoc PLoc,
0153                           StringRef ModuleName) override;
0154 
0155   void emitBuildingModuleLocation(FullSourceLoc Loc, PresumedLoc PLoc,
0156                                   StringRef ModuleName) override;
0157 
0158   virtual void emitNote(FullSourceLoc Loc, StringRef Message) = 0;
0159 };
0160 
0161 } // namespace clang
0162 
0163 #endif // LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H