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 25 namespace 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. 35 class SourceMgr { 36 public: 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); 47 private: 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; 73 public: 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(SMLoc Loc, DiagKind Kind, const Twine &Msg, 148 ArrayRef<SMRange> Ranges = None, 149 ArrayRef<SMFixIt> FixIts = None, 150 bool ShowColors = true) const; 151 152 153 /// GetMessage - Return an SMDiagnostic at the specified location with the 154 /// specified string. 155 /// 156 /// @param Msg If non-null, the kind of message (e.g., "error") which is 157 /// prefixed to the message. 158 SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, 159 ArrayRef<SMRange> Ranges = None, 160 ArrayRef<SMFixIt> FixIts = None) const; 161 162 /// PrintIncludeStack - Prints the names of included files and the line of the 163 /// file they were included from. A diagnostic handler can use this before 164 /// printing its custom formatted message. 165 /// 166 /// @param IncludeLoc - The line of the include. 167 /// @param OS the raw_ostream to print on. 168 void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const; 169 }; 170 171 172 /// Represents a single fixit, a replacement of one range of text with another. 173 class SMFixIt { 174 SMRange Range; 175 176 std::string Text; 177 178 public: 179 // FIXME: Twine.str() is not very efficient. 180 SMFixIt(SMLoc Loc, const Twine &Insertion) 181 : Range(Loc, Loc), Text(Insertion.str()) { 182 assert(Loc.isValid()); 183 } 184 185 // FIXME: Twine.str() is not very efficient. 186 SMFixIt(SMRange R, const Twine &Replacement) 187 : Range(R), Text(Replacement.str()) { 188 assert(R.isValid()); 189 } 190 191 StringRef getText() const { return Text; } 192 SMRange getRange() const { return Range; } 193 194 bool operator<(const SMFixIt &Other) const { 195 if (Range.Start.getPointer() != Other.Range.Start.getPointer()) 196 return Range.Start.getPointer() < Other.Range.Start.getPointer(); 197 if (Range.End.getPointer() != Other.Range.End.getPointer()) 198 return Range.End.getPointer() < Other.Range.End.getPointer(); 199 return Text < Other.Text; 200 } 201 }; 202 203 204 /// SMDiagnostic - Instances of this class encapsulate one diagnostic report, 205 /// allowing printing to a raw_ostream as a caret diagnostic. 206 class SMDiagnostic { 207 const SourceMgr *SM; 208 SMLoc Loc; 209 std::string Filename; 210 int LineNo, ColumnNo; 211 SourceMgr::DiagKind Kind; 212 std::string Message, LineContents; 213 std::vector<std::pair<unsigned, unsigned> > Ranges; 214 SmallVector<SMFixIt, 4> FixIts; 215 216 public: 217 // Null diagnostic. 218 SMDiagnostic() 219 : SM(0), LineNo(0), ColumnNo(0), Kind(SourceMgr::DK_Error) {} 220 // Diagnostic with no location (e.g. file not found, command line arg error). 221 SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg) 222 : SM(0), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), 223 Message(Msg) {} 224 225 // Diagnostic with a location. 226 SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN, 227 int Line, int Col, SourceMgr::DiagKind Kind, 228 StringRef Msg, StringRef LineStr, 229 ArrayRef<std::pair<unsigned,unsigned> > Ranges, 230 ArrayRef<SMFixIt> FixIts = None); 231 232 const SourceMgr *getSourceMgr() const { return SM; } 233 SMLoc getLoc() const { return Loc; } 234 StringRef getFilename() const { return Filename; } 235 int getLineNo() const { return LineNo; } 236 int getColumnNo() const { return ColumnNo; } 237 SourceMgr::DiagKind getKind() const { return Kind; } 238 StringRef getMessage() const { return Message; } 239 StringRef getLineContents() const { return LineContents; } 240 ArrayRef<std::pair<unsigned, unsigned> > getRanges() const { 241 return Ranges; 242 } 243 244 void addFixIt(const SMFixIt &Hint) { 245 FixIts.push_back(Hint); 246 } 247 248 ArrayRef<SMFixIt> getFixIts() const { 249 return FixIts; 250 } 251 252 void print(const char *ProgName, raw_ostream &S, 253 bool ShowColors = true) const; 254 }; 255 256 } // end llvm namespace 257 258 #endif 259