LCOV - code coverage report
Current view: top level - include/llvm/Support - SourceMgr.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 28 34 82.4 %
Date: 2017-09-14 15:23:50 Functions: 5 7 71.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- SourceMgr.h - Manager for Source Buffers & Diagnostics ---*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This file declares the SMDiagnostic and SourceMgr classes.  This
      11             : // provides a simple substrate for diagnostics, #include handling, and other low
      12             : // level things for simple parsers.
      13             : //
      14             : //===----------------------------------------------------------------------===//
      15             : 
      16             : #ifndef LLVM_SUPPORT_SOURCEMGR_H
      17             : #define LLVM_SUPPORT_SOURCEMGR_H
      18             : 
      19             : #include "llvm/ADT/ArrayRef.h"
      20             : #include "llvm/ADT/None.h"
      21             : #include "llvm/ADT/SmallVector.h"
      22             : #include "llvm/ADT/StringRef.h"
      23             : #include "llvm/ADT/Twine.h"
      24             : #include "llvm/Support/MemoryBuffer.h"
      25             : #include "llvm/Support/SMLoc.h"
      26             : #include <algorithm>
      27             : #include <cassert>
      28             : #include <memory>
      29             : #include <string>
      30             : #include <utility>
      31             : #include <vector>
      32             : 
      33             : namespace llvm {
      34             : 
      35             : class raw_ostream;
      36             : class SMDiagnostic;
      37             : class SMFixIt;
      38             : 
      39             : /// This owns the files read by a parser, handles include stacks,
      40             : /// and handles diagnostic wrangling.
      41             : class SourceMgr {
      42             : public:
      43             :   enum DiagKind {
      44             :     DK_Error,
      45             :     DK_Warning,
      46             :     DK_Note
      47             :   };
      48             : 
      49             :   /// Clients that want to handle their own diagnostics in a custom way can
      50             :   /// register a function pointer+context as a diagnostic handler.
      51             :   /// It gets called each time PrintMessage is invoked.
      52             :   using DiagHandlerTy = void (*)(const SMDiagnostic &, void *Context);
      53             : 
      54             : private:
      55     2724798 :   struct SrcBuffer {
      56             :     /// The memory buffer for the file.
      57             :     std::unique_ptr<MemoryBuffer> Buffer;
      58             : 
      59             :     /// This is the location of the parent include, or null if at the top level.
      60             :     SMLoc IncludeLoc;
      61             :   };
      62             : 
      63             :   /// This is all of the buffers that we are reading from.
      64             :   std::vector<SrcBuffer> Buffers;
      65             : 
      66             :   // This is the list of directories we should search for include files in.
      67             :   std::vector<std::string> IncludeDirectories;
      68             : 
      69             :   /// This is a cache for line number queries, its implementation is really
      70             :   /// private to SourceMgr.cpp.
      71             :   mutable void *LineNoCache = nullptr;
      72             : 
      73             :   DiagHandlerTy DiagHandler = nullptr;
      74             :   void *DiagContext = nullptr;
      75             : 
      76             :   bool isValidBufferID(unsigned i) const { return i && i <= Buffers.size(); }
      77             : 
      78             : public:
      79      262617 :   SourceMgr() = default;
      80             :   SourceMgr(const SourceMgr &) = delete;
      81             :   SourceMgr &operator=(const SourceMgr &) = delete;
      82             :   ~SourceMgr();
      83             : 
      84             :   void setIncludeDirs(const std::vector<std::string> &Dirs) {
      85        7843 :     IncludeDirectories = Dirs;
      86             :   }
      87             : 
      88             :   /// Specify a diagnostic handler to be invoked every time PrintMessage is
      89             :   /// called. \p Ctx is passed into the handler when it is invoked.
      90             :   void setDiagHandler(DiagHandlerTy DH, void *Ctx = nullptr) {
      91       16357 :     DiagHandler = DH;
      92       16357 :     DiagContext = Ctx;
      93             :   }
      94             : 
      95             :   DiagHandlerTy getDiagHandler() const { return DiagHandler; }
      96             :   void *getDiagContext() const { return DiagContext; }
      97             : 
      98             :   const SrcBuffer &getBufferInfo(unsigned i) const {
      99             :     assert(isValidBufferID(i));
     100        6374 :     return Buffers[i - 1];
     101             :   }
     102             : 
     103             :   const MemoryBuffer *getMemoryBuffer(unsigned i) const {
     104             :     assert(isValidBufferID(i));
     105     1278610 :     return Buffers[i - 1].Buffer.get();
     106             :   }
     107             : 
     108             :   unsigned getNumBuffers() const {
     109        9908 :     return Buffers.size();
     110             :   }
     111             : 
     112             :   unsigned getMainFileID() const {
     113             :     assert(getNumBuffers());
     114             :     return 1;
     115             :   }
     116             : 
     117             :   SMLoc getParentIncludeLoc(unsigned i) const {
     118             :     assert(isValidBufferID(i));
     119       28028 :     return Buffers[i - 1].IncludeLoc;
     120             :   }
     121             : 
     122             :   /// Add a new source buffer to this source manager. This takes ownership of
     123             :   /// the memory buffer.
     124      305535 :   unsigned AddNewSourceBuffer(std::unique_ptr<MemoryBuffer> F,
     125             :                               SMLoc IncludeLoc) {
     126      611070 :     SrcBuffer NB;
     127      611070 :     NB.Buffer = std::move(F);
     128      305535 :     NB.IncludeLoc = IncludeLoc;
     129      611070 :     Buffers.push_back(std::move(NB));
     130      916605 :     return Buffers.size();
     131             :   }
     132             : 
     133             :   /// Search for a file with the specified name in the current directory or in
     134             :   /// one of the IncludeDirs.
     135             :   ///
     136             :   /// If no file is found, this returns 0, otherwise it returns the buffer ID
     137             :   /// of the stacked file. The full path to the included file can be found in
     138             :   /// \p IncludedFile.
     139             :   unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc,
     140             :                           std::string &IncludedFile);
     141             : 
     142             :   /// Return the ID of the buffer containing the specified location.
     143             :   ///
     144             :   /// 0 is returned if the buffer is not found.
     145             :   unsigned FindBufferContainingLoc(SMLoc Loc) const;
     146             : 
     147             :   /// Find the line number for the specified location in the specified file.
     148             :   /// This is not a fast method.
     149             :   unsigned FindLineNumber(SMLoc Loc, unsigned BufferID = 0) const {
     150         182 :     return getLineAndColumn(Loc, BufferID).first;
     151             :   }
     152             : 
     153             :   /// Find the line and column number for the specified location in the
     154             :   /// specified file. This is not a fast method.
     155             :   std::pair<unsigned, unsigned> getLineAndColumn(SMLoc Loc,
     156             :                                                  unsigned BufferID = 0) const;
     157             : 
     158             :   /// Emit a message about the specified location with the specified string.
     159             :   ///
     160             :   /// \param ShowColors Display colored messages if output is a terminal and
     161             :   /// the default error handler is used.
     162             :   void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind,
     163             :                     const Twine &Msg,
     164             :                     ArrayRef<SMRange> Ranges = None,
     165             :                     ArrayRef<SMFixIt> FixIts = None,
     166             :                     bool ShowColors = true) const;
     167             : 
     168             :   /// Emits a diagnostic to llvm::errs().
     169             :   void PrintMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg,
     170             :                     ArrayRef<SMRange> Ranges = None,
     171             :                     ArrayRef<SMFixIt> FixIts = None,
     172             :                     bool ShowColors = true) const;
     173             : 
     174             :   /// Emits a manually-constructed diagnostic to the given output stream.
     175             :   ///
     176             :   /// \param ShowColors Display colored messages if output is a terminal and
     177             :   /// the default error handler is used.
     178             :   void PrintMessage(raw_ostream &OS, const SMDiagnostic &Diagnostic,
     179             :                     bool ShowColors = true) const;
     180             : 
     181             :   /// Return an SMDiagnostic at the specified location with the specified
     182             :   /// string.
     183             :   ///
     184             :   /// \param Msg If non-null, the kind of message (e.g., "error") which is
     185             :   /// prefixed to the message.
     186             :   SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg,
     187             :                           ArrayRef<SMRange> Ranges = None,
     188             :                           ArrayRef<SMFixIt> FixIts = None) const;
     189             : 
     190             :   /// Prints the names of included files and the line of the file they were
     191             :   /// included from. A diagnostic handler can use this before printing its
     192             :   /// custom formatted message.
     193             :   ///
     194             :   /// \param IncludeLoc The location of the include.
     195             :   /// \param OS the raw_ostream to print on.
     196             :   void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const;
     197             : };
     198             : 
     199             : /// Represents a single fixit, a replacement of one range of text with another.
     200         180 : class SMFixIt {
     201             :   SMRange Range;
     202             : 
     203             :   std::string Text;
     204             : 
     205             : public:
     206             :   // FIXME: Twine.str() is not very efficient.
     207             :   SMFixIt(SMLoc Loc, const Twine &Insertion)
     208             :     : Range(Loc, Loc), Text(Insertion.str()) {
     209             :     assert(Loc.isValid());
     210             :   }
     211             : 
     212             :   // FIXME: Twine.str() is not very efficient.
     213             :   SMFixIt(SMRange R, const Twine &Replacement)
     214          30 :     : Range(R), Text(Replacement.str()) {
     215             :     assert(R.isValid());
     216             :   }
     217             : 
     218         232 :   StringRef getText() const { return Text; }
     219             :   SMRange getRange() const { return Range; }
     220             : 
     221           0 :   bool operator<(const SMFixIt &Other) const {
     222           0 :     if (Range.Start.getPointer() != Other.Range.Start.getPointer())
     223           0 :       return Range.Start.getPointer() < Other.Range.Start.getPointer();
     224           0 :     if (Range.End.getPointer() != Other.Range.End.getPointer())
     225           0 :       return Range.End.getPointer() < Other.Range.End.getPointer();
     226           0 :     return Text < Other.Text;
     227             :   }
     228             : };
     229             : 
     230             : /// Instances of this class encapsulate one diagnostic report, allowing
     231             : /// printing to a raw_ostream as a caret diagnostic.
     232      425464 : class SMDiagnostic {
     233             :   const SourceMgr *SM = nullptr;
     234             :   SMLoc Loc;
     235             :   std::string Filename;
     236             :   int LineNo = 0;
     237             :   int ColumnNo = 0;
     238             :   SourceMgr::DiagKind Kind = SourceMgr::DK_Error;
     239             :   std::string Message, LineContents;
     240             :   std::vector<std::pair<unsigned, unsigned>> Ranges;
     241             :   SmallVector<SMFixIt, 4> FixIts;
     242             : 
     243             : public:
     244             :   // Null diagnostic.
     245      240807 :   SMDiagnostic() = default;
     246             :   // Diagnostic with no location (e.g. file not found, command line arg error).
     247           5 :   SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg)
     248          35 :     : Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), Message(Msg) {}
     249             : 
     250             :   // Diagnostic with a location.
     251             :   SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN,
     252             :                int Line, int Col, SourceMgr::DiagKind Kind,
     253             :                StringRef Msg, StringRef LineStr,
     254             :                ArrayRef<std::pair<unsigned,unsigned>> Ranges,
     255             :                ArrayRef<SMFixIt> FixIts = None);
     256             : 
     257             :   const SourceMgr *getSourceMgr() const { return SM; }
     258             :   SMLoc getLoc() const { return Loc; }
     259           6 :   StringRef getFilename() const { return Filename; }
     260             :   int getLineNo() const { return LineNo; }
     261             :   int getColumnNo() const { return ColumnNo; }
     262             :   SourceMgr::DiagKind getKind() const { return Kind; }
     263         336 :   StringRef getMessage() const { return Message; }
     264         434 :   StringRef getLineContents() const { return LineContents; }
     265         268 :   ArrayRef<std::pair<unsigned, unsigned>> getRanges() const { return Ranges; }
     266             : 
     267             :   void addFixIt(const SMFixIt &Hint) {
     268             :     FixIts.push_back(Hint);
     269             :   }
     270             : 
     271             :   ArrayRef<SMFixIt> getFixIts() const {
     272         190 :     return FixIts;
     273             :   }
     274             : 
     275             :   void print(const char *ProgName, raw_ostream &S, bool ShowColors = true,
     276             :              bool ShowKindLabel = true) const;
     277             : };
     278             : 
     279             : } // end namespace llvm
     280             : 
     281             : #endif // LLVM_SUPPORT_SOURCEMGR_H

Generated by: LCOV version 1.13