llvm.org GIT mirror llvm / 9ed0c7a include / llvm / Support / SourceMgr.h
9ed0c7a

Tree @9ed0c7a (Download .tar.gz)

SourceMgr.h @9ed0c7a

099e198
aa739d2
 
 
 
 
 
 
 
1ae486a
2f510ae
 
aa739d2
 
 
674be02
 
aa739d2
d8b7aa2
9b1f44b
 
95ca0fb
255f89f
1d876b7
aa739d2
 
8070ea3
2f510ae
9b1f44b
d1e1703
2f510ae
aa739d2
ecb1c3a
2f510ae
8070ea3
8f0f480
3f2d5f6
 
 
 
 
ac9e819
ecb1c3a
 
 
3f2d5f6
8f0f480
aa739d2
ecb1c3a
95ca0fb
e690ffb
ecb1c3a
1e3a8a4
aa739d2
e690ffb
ecb1c3a
aa739d2
e690ffb
ecb1c3a
7ee5d5f
e690ffb
ecb1c3a
 
1d96ccc
e690ffb
8f0f480
 
f630e49
1508c82
 
66981fe
 
aa739d2
34bc6b6
 
8070ea3
e690ffb
7ee5d5f
 
 
e690ffb
ecb1c3a
 
34bc6b6
8f0f480
 
 
 
04a0426
 
 
aa739d2
1508c82
 
aa739d2
 
 
1508c82
95ca0fb
aa739d2
e690ffb
7b39c06
6c58314
 
 
1508c82
 
 
 
 
1e3a8a4
1508c82
 
aa739d2
e690ffb
ecb1c3a
 
95ca0fb
 
aa739d2
95ca0fb
aa739d2
95ca0fb
1508c82
aa739d2
e690ffb
ecb1c3a
 
 
1508c82
ecb1c3a
 
7b39c06
 
e690ffb
ecb1c3a
 
1508c82
 
e690ffb
ecb1c3a
 
1508c82
77eafd9
 
 
ecb1c3a
 
1508c82
 
e690ffb
ecb1c3a
3fb7683
ecb1c3a
89f33fd
8a93c3a
 
5c332db
 
89f33fd
e690ffb
8a93c3a
 
 
 
 
e690ffb
4e23baa
 
 
 
 
 
 
ecb1c3a
 
eeb4a84
ecb1c3a
eeb4a84
5c332db
 
 
e690ffb
ecb1c3a
 
 
acbaecd
ecb1c3a
 
2f510ae
 
 
e690ffb
9b1f44b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ecb1c3a
 
2f510ae
b019491
8f0f480
2f510ae
 
3f2d5f6
2f510ae
d8b7aa2
9b1f44b
4153982
2f510ae
b019491
3f2d5f6
34bc6b6
b019491
9b1f44b
34bc6b6
462b43c
ac9e819
b019491
9b1f44b
3f2d5f6
9b1f44b
 
5c332db
2f510ae
b019491
8f0f480
9b1f44b
8f0f480
 
3f2d5f6
9b1f44b
 
 
d8b7aa2
 
9b1f44b
 
 
 
 
 
 
 
 
a15d888
 
aa739d2
e690ffb
cd52a7a
aa739d2
 
//===- SourceMgr.h - Manager for Source Buffers & Diagnostics ---*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares the SMDiagnostic and SourceMgr classes.  This
// provides a simple substrate for diagnostics, #include handling, and other low
// level things for simple parsers.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_SUPPORT_SOURCEMGR_H
#define LLVM_SUPPORT_SOURCEMGR_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SMLoc.h"
#include <string>

namespace llvm {
  class SourceMgr;
  class SMDiagnostic;
  class SMFixIt;
  class Twine;
  class raw_ostream;

/// This owns the files read by a parser, handles include stacks,
/// and handles diagnostic wrangling.
class SourceMgr {
public:
  enum DiagKind {
    DK_Error,
    DK_Warning,
    DK_Note
  };

  /// Clients that want to handle their own diagnostics in a custom way can
  /// register a function pointer+context as a diagnostic handler.
  /// It gets called each time PrintMessage is invoked.
  typedef void (*DiagHandlerTy)(const SMDiagnostic &, void *Context);
private:
  struct SrcBuffer {
    /// The memory buffer for the file.
    std::unique_ptr<MemoryBuffer> Buffer;

    /// This is the location of the parent include, or null if at the top level.
    SMLoc IncludeLoc;
  };

  /// This is all of the buffers that we are reading from.
  std::vector<SrcBuffer> Buffers;

  // This is the list of directories we should search for include files in.
  std::vector<std::string> IncludeDirectories;

  /// This is a cache for line number queries, its implementation is really
  /// private to SourceMgr.cpp.
  mutable void *LineNoCache;

  DiagHandlerTy DiagHandler;
  void *DiagContext;

  bool isValidBufferID(unsigned i) const { return i && i <= Buffers.size(); }

  SourceMgr(const SourceMgr&) = delete;
  void operator=(const SourceMgr&) = delete;
public:
  SourceMgr()
    : LineNoCache(nullptr), DiagHandler(nullptr), DiagContext(nullptr) {}
  ~SourceMgr();

  void setIncludeDirs(const std::vector<std::string> &Dirs) {
    IncludeDirectories = Dirs;
  }

  /// Specify a diagnostic handler to be invoked every time PrintMessage is
  /// called. \p Ctx is passed into the handler when it is invoked.
  void setDiagHandler(DiagHandlerTy DH, void *Ctx = nullptr) {
    DiagHandler = DH;
    DiagContext = Ctx;
  }

  DiagHandlerTy getDiagHandler() const { return DiagHandler; }
  void *getDiagContext() const { return DiagContext; }

  const SrcBuffer &getBufferInfo(unsigned i) const {
    assert(isValidBufferID(i));
    return Buffers[i - 1];
  }

  const MemoryBuffer *getMemoryBuffer(unsigned i) const {
    assert(isValidBufferID(i));
    return Buffers[i - 1].Buffer.get();
  }

  unsigned getNumBuffers() const {
    return Buffers.size();
  }

  unsigned getMainFileID() const {
    assert(getNumBuffers());
    return 1;
  }

  SMLoc getParentIncludeLoc(unsigned i) const {
    assert(isValidBufferID(i));
    return Buffers[i - 1].IncludeLoc;
  }

  /// Add a new source buffer to this source manager. This takes ownership of
  /// the memory buffer.
  unsigned AddNewSourceBuffer(std::unique_ptr<MemoryBuffer> F,
                              SMLoc IncludeLoc) {
    SrcBuffer NB;
    NB.Buffer = std::move(F);
    NB.IncludeLoc = IncludeLoc;
    Buffers.push_back(std::move(NB));
    return Buffers.size();
  }

  /// Search for a file with the specified name in the current directory or in
  /// one of the IncludeDirs.
  ///
  /// If no file is found, this returns 0, otherwise it returns the buffer ID
  /// of the stacked file. The full path to the included file can be found in
  /// \p IncludedFile.
  unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc,
                          std::string &IncludedFile);

  /// Return the ID of the buffer containing the specified location.
  ///
  /// 0 is returned if the buffer is not found.
  unsigned FindBufferContainingLoc(SMLoc Loc) const;

  /// Find the line number for the specified location in the specified file.
  /// This is not a fast method.
  unsigned FindLineNumber(SMLoc Loc, unsigned BufferID = 0) const {
    return getLineAndColumn(Loc, BufferID).first;
  }

  /// Find the line and column number for the specified location in the
  /// specified file. This is not a fast method.
  std::pair<unsigned, unsigned> getLineAndColumn(SMLoc Loc,
                                                 unsigned BufferID = 0) const;

  /// Emit a message about the specified location with the specified string.
  ///
  /// \param ShowColors Display colored messages if output is a terminal and
  /// the default error handler is used.
  void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind,
                    const Twine &Msg,
                    ArrayRef<SMRange> Ranges = None,
                    ArrayRef<SMFixIt> FixIts = None,
                    bool ShowColors = true) const;

  /// Emits a diagnostic to llvm::errs().
  void PrintMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg,
                    ArrayRef<SMRange> Ranges = None,
                    ArrayRef<SMFixIt> FixIts = None,
                    bool ShowColors = true) const;

  /// Emits a manually-constructed diagnostic to the given output stream.
  ///
  /// \param ShowColors Display colored messages if output is a terminal and
  /// the default error handler is used.
  void PrintMessage(raw_ostream &OS, const SMDiagnostic &Diagnostic,
                    bool ShowColors = true) const;

  /// Return an SMDiagnostic at the specified location with the specified
  /// string.
  ///
  /// \param Msg If non-null, the kind of message (e.g., "error") which is
  /// prefixed to the message.
  SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg,
                          ArrayRef<SMRange> Ranges = None,
                          ArrayRef<SMFixIt> FixIts = None) const;

  /// Prints the names of included files and the line of the file they were
  /// included from. A diagnostic handler can use this before printing its
  /// custom formatted message.
  ///
  /// \param IncludeLoc The location of the include.
  /// \param OS the raw_ostream to print on.
  void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const;
};


/// Represents a single fixit, a replacement of one range of text with another.
class SMFixIt {
  SMRange Range;

  std::string Text;

public:
  // FIXME: Twine.str() is not very efficient.
  SMFixIt(SMLoc Loc, const Twine &Insertion)
    : Range(Loc, Loc), Text(Insertion.str()) {
    assert(Loc.isValid());
  }

  // FIXME: Twine.str() is not very efficient.
  SMFixIt(SMRange R, const Twine &Replacement)
    : Range(R), Text(Replacement.str()) {
    assert(R.isValid());
  }

  StringRef getText() const { return Text; }
  SMRange getRange() const { return Range; }

  bool operator<(const SMFixIt &Other) const {
    if (Range.Start.getPointer() != Other.Range.Start.getPointer())
      return Range.Start.getPointer() < Other.Range.Start.getPointer();
    if (Range.End.getPointer() != Other.Range.End.getPointer())
      return Range.End.getPointer() < Other.Range.End.getPointer();
    return Text < Other.Text;
  }
};


/// Instances of this class encapsulate one diagnostic report, allowing
/// printing to a raw_ostream as a caret diagnostic.
class SMDiagnostic {
  const SourceMgr *SM;
  SMLoc Loc;
  std::string Filename;
  int LineNo, ColumnNo;
  SourceMgr::DiagKind Kind;
  std::string Message, LineContents;
  std::vector<std::pair<unsigned, unsigned> > Ranges;
  SmallVector<SMFixIt, 4> FixIts;

public:
  // Null diagnostic.
  SMDiagnostic()
    : SM(nullptr), LineNo(0), ColumnNo(0), Kind(SourceMgr::DK_Error) {}
  // Diagnostic with no location (e.g. file not found, command line arg error).
  SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg)
    : SM(nullptr), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd),
      Message(Msg) {}

  // Diagnostic with a location.
  SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN,
               int Line, int Col, SourceMgr::DiagKind Kind,
               StringRef Msg, StringRef LineStr,
               ArrayRef<std::pair<unsigned,unsigned> > Ranges,
               ArrayRef<SMFixIt> FixIts = None);

  const SourceMgr *getSourceMgr() const { return SM; }
  SMLoc getLoc() const { return Loc; }
  StringRef getFilename() const { return Filename; }
  int getLineNo() const { return LineNo; }
  int getColumnNo() const { return ColumnNo; }
  SourceMgr::DiagKind getKind() const { return Kind; }
  StringRef getMessage() const { return Message; }
  StringRef getLineContents() const { return LineContents; }
  ArrayRef<std::pair<unsigned, unsigned> > getRanges() const {
    return Ranges;
  }

  void addFixIt(const SMFixIt &Hint) {
    FixIts.push_back(Hint);
  }

  ArrayRef<SMFixIt> getFixIts() const {
    return FixIts;
  }

  void print(const char *ProgName, raw_ostream &S, bool ShowColors = true,
             bool ShowKindLabel = true) const;
};

}  // end llvm namespace

#endif