Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

258 lines
8.6 KiB

  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. #ifndef LLVM_SUPPORT_SOURCEMGR_H
  16. #define LLVM_SUPPORT_SOURCEMGR_H
  17. #include "llvm/ADT/ArrayRef.h"
  18. #include "llvm/ADT/StringRef.h"
  19. #include "llvm/ADT/Twine.h"
  20. #include "llvm/Support/SMLoc.h"
  21. #include <string>
  22. namespace llvm {
  23. class MemoryBuffer;
  24. class SourceMgr;
  25. class SMDiagnostic;
  26. class SMFixIt;
  27. class Twine;
  28. class raw_ostream;
  29. /// SourceMgr - This owns the files read by a parser, handles include stacks,
  30. /// and handles diagnostic wrangling.
  31. class SourceMgr {
  32. public:
  33. enum DiagKind {
  34. DK_Error,
  35. DK_Warning,
  36. DK_Note
  37. };
  38. /// DiagHandlerTy - Clients that want to handle their own diagnostics in a
  39. /// custom way can register a function pointer+context as a diagnostic
  40. /// handler. It gets called each time PrintMessage is invoked.
  41. typedef void (*DiagHandlerTy)(const SMDiagnostic &, void *Context);
  42. private:
  43. struct SrcBuffer {
  44. /// Buffer - The memory buffer for the file.
  45. MemoryBuffer *Buffer;
  46. /// IncludeLoc - This is the location of the parent include, or null if at
  47. /// the top level.
  48. SMLoc IncludeLoc;
  49. };
  50. /// Buffers - This is all of the buffers that we are reading from.
  51. std::vector<SrcBuffer> Buffers;
  52. // IncludeDirectories - This is the list of directories we should search for
  53. // include files in.
  54. std::vector<std::string> IncludeDirectories;
  55. /// LineNoCache - This is a cache for line number queries, its implementation
  56. /// is really private to SourceMgr.cpp.
  57. mutable void *LineNoCache;
  58. DiagHandlerTy DiagHandler;
  59. void *DiagContext;
  60. SourceMgr(const SourceMgr&) LLVM_DELETED_FUNCTION;
  61. void operator=(const SourceMgr&) LLVM_DELETED_FUNCTION;
  62. public:
  63. SourceMgr() : LineNoCache(0), DiagHandler(0), DiagContext(0) {}
  64. ~SourceMgr();
  65. void setIncludeDirs(const std::vector<std::string> &Dirs) {
  66. IncludeDirectories = Dirs;
  67. }
  68. /// setDiagHandler - Specify a diagnostic handler to be invoked every time
  69. /// PrintMessage is called. Ctx is passed into the handler when it is invoked.
  70. void setDiagHandler(DiagHandlerTy DH, void *Ctx = 0) {
  71. DiagHandler = DH;
  72. DiagContext = Ctx;
  73. }
  74. DiagHandlerTy getDiagHandler() const { return DiagHandler; }
  75. void *getDiagContext() const { return DiagContext; }
  76. const SrcBuffer &getBufferInfo(unsigned i) const {
  77. assert(i < Buffers.size() && "Invalid Buffer ID!");
  78. return Buffers[i];
  79. }
  80. const MemoryBuffer *getMemoryBuffer(unsigned i) const {
  81. assert(i < Buffers.size() && "Invalid Buffer ID!");
  82. return Buffers[i].Buffer;
  83. }
  84. unsigned getNumBuffers() const {
  85. return Buffers.size();
  86. }
  87. SMLoc getParentIncludeLoc(unsigned i) const {
  88. assert(i < Buffers.size() && "Invalid Buffer ID!");
  89. return Buffers[i].IncludeLoc;
  90. }
  91. /// AddNewSourceBuffer - Add a new source buffer to this source manager. This
  92. /// takes ownership of the memory buffer.
  93. unsigned AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) {
  94. SrcBuffer NB;
  95. NB.Buffer = F;
  96. NB.IncludeLoc = IncludeLoc;
  97. Buffers.push_back(NB);
  98. return Buffers.size()-1;
  99. }
  100. /// AddIncludeFile - Search for a file with the specified name in the current
  101. /// directory or in one of the IncludeDirs. If no file is found, this returns
  102. /// ~0, otherwise it returns the buffer ID of the stacked file.
  103. /// The full path to the included file can be found in IncludedFile.
  104. unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc,
  105. std::string &IncludedFile);
  106. /// FindBufferContainingLoc - Return the ID of the buffer containing the
  107. /// specified location, returning -1 if not found.
  108. int FindBufferContainingLoc(SMLoc Loc) const;
  109. /// FindLineNumber - Find the line number for the specified location in the
  110. /// specified file. This is not a fast method.
  111. unsigned FindLineNumber(SMLoc Loc, int BufferID = -1) const {
  112. return getLineAndColumn(Loc, BufferID).first;
  113. }
  114. /// getLineAndColumn - Find the line and column number for the specified
  115. /// location in the specified file. This is not a fast method.
  116. std::pair<unsigned, unsigned>
  117. getLineAndColumn(SMLoc Loc, int BufferID = -1) const;
  118. /// PrintMessage - Emit a message about the specified location with the
  119. /// specified string.
  120. ///
  121. /// @param ShowColors - Display colored messages if output is a terminal and
  122. /// the default error handler is used.
  123. void PrintMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg,
  124. ArrayRef<SMRange> Ranges = ArrayRef<SMRange>(),
  125. ArrayRef<SMFixIt> FixIts = ArrayRef<SMFixIt>(),
  126. bool ShowColors = true) const;
  127. /// GetMessage - Return an SMDiagnostic at the specified location with the
  128. /// specified string.
  129. ///
  130. /// @param Msg If non-null, the kind of message (e.g., "error") which is
  131. /// prefixed to the message.
  132. SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg,
  133. ArrayRef<SMRange> Ranges = ArrayRef<SMRange>(),
  134. ArrayRef<SMFixIt> FixIts = ArrayRef<SMFixIt>()) const;
  135. /// PrintIncludeStack - Prints the names of included files and the line of the
  136. /// file they were included from. A diagnostic handler can use this before
  137. /// printing its custom formatted message.
  138. ///
  139. /// @param IncludeLoc - The line of the include.
  140. /// @param OS the raw_ostream to print on.
  141. void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const;
  142. };
  143. /// Represents a single fixit, a replacement of one range of text with another.
  144. class SMFixIt {
  145. SMRange Range;
  146. std::string Text;
  147. public:
  148. // FIXME: Twine.str() is not very efficient.
  149. SMFixIt(SMLoc Loc, const Twine &Insertion)
  150. : Range(Loc, Loc), Text(Insertion.str()) {
  151. assert(Loc.isValid());
  152. }
  153. // FIXME: Twine.str() is not very efficient.
  154. SMFixIt(SMRange R, const Twine &Replacement)
  155. : Range(R), Text(Replacement.str()) {
  156. assert(R.isValid());
  157. }
  158. StringRef getText() const { return Text; }
  159. SMRange getRange() const { return Range; }
  160. bool operator<(const SMFixIt &Other) const {
  161. if (Range.Start.getPointer() != Other.Range.Start.getPointer())
  162. return Range.Start.getPointer() < Other.Range.Start.getPointer();
  163. if (Range.End.getPointer() != Other.Range.End.getPointer())
  164. return Range.End.getPointer() < Other.Range.End.getPointer();
  165. return Text < Other.Text;
  166. }
  167. };
  168. /// SMDiagnostic - Instances of this class encapsulate one diagnostic report,
  169. /// allowing printing to a raw_ostream as a caret diagnostic.
  170. class SMDiagnostic {
  171. const SourceMgr *SM;
  172. SMLoc Loc;
  173. std::string Filename;
  174. int LineNo, ColumnNo;
  175. SourceMgr::DiagKind Kind;
  176. std::string Message, LineContents;
  177. std::vector<std::pair<unsigned, unsigned> > Ranges;
  178. SmallVector<SMFixIt, 4> FixIts;
  179. public:
  180. // Null diagnostic.
  181. SMDiagnostic()
  182. : SM(0), LineNo(0), ColumnNo(0), Kind(SourceMgr::DK_Error) {}
  183. // Diagnostic with no location (e.g. file not found, command line arg error).
  184. SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg)
  185. : SM(0), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd),
  186. Message(Msg) {}
  187. // Diagnostic with a location.
  188. SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN,
  189. int Line, int Col, SourceMgr::DiagKind Kind,
  190. StringRef Msg, StringRef LineStr,
  191. ArrayRef<std::pair<unsigned,unsigned> > Ranges,
  192. ArrayRef<SMFixIt> FixIts = ArrayRef<SMFixIt>());
  193. const SourceMgr *getSourceMgr() const { return SM; }
  194. SMLoc getLoc() const { return Loc; }
  195. StringRef getFilename() const { return Filename; }
  196. int getLineNo() const { return LineNo; }
  197. int getColumnNo() const { return ColumnNo; }
  198. SourceMgr::DiagKind getKind() const { return Kind; }
  199. StringRef getMessage() const { return Message; }
  200. StringRef getLineContents() const { return LineContents; }
  201. ArrayRef<std::pair<unsigned, unsigned> > getRanges() const {
  202. return Ranges;
  203. }
  204. void addFixIt(const SMFixIt &Hint) {
  205. FixIts.push_back(Hint);
  206. }
  207. ArrayRef<SMFixIt> getFixIts() const {
  208. return FixIts;
  209. }
  210. void print(const char *ProgName, raw_ostream &S,
  211. bool ShowColors = true) const;
  212. };
  213. } // end llvm namespace
  214. #endif