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