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

Generated by: LCOV version 1.13