1194612Sed//===- SourceMgr.h - Manager for Source Buffers & Diagnostics ---*- C++ -*-===// 2194612Sed// 3194612Sed// The LLVM Compiler Infrastructure 4194612Sed// 5194612Sed// This file is distributed under the University of Illinois Open Source 6194612Sed// License. See LICENSE.TXT for details. 7194612Sed// 8194612Sed//===----------------------------------------------------------------------===// 9194612Sed// 10202878Srdivacky// This file declares the SMDiagnostic and SourceMgr classes. This 11195340Sed// provides a simple substrate for diagnostics, #include handling, and other low 12195340Sed// level things for simple parsers. 13194612Sed// 14194612Sed//===----------------------------------------------------------------------===// 15194612Sed 16249423Sdim#ifndef LLVM_SUPPORT_SOURCEMGR_H 17249423Sdim#define LLVM_SUPPORT_SOURCEMGR_H 18194612Sed 19249423Sdim#include "llvm/ADT/ArrayRef.h" 20249423Sdim#include "llvm/ADT/StringRef.h" 21249423Sdim#include "llvm/ADT/Twine.h" 22202878Srdivacky#include "llvm/Support/SMLoc.h" 23194612Sed#include <string> 24194612Sed 25194612Sednamespace llvm { 26194612Sed class MemoryBuffer; 27194612Sed class SourceMgr; 28195340Sed class SMDiagnostic; 29249423Sdim class SMFixIt; 30218893Sdim class Twine; 31195340Sed class raw_ostream; 32195340Sed 33195340Sed/// SourceMgr - This owns the files read by a parser, handles include stacks, 34195340Sed/// and handles diagnostic wrangling. 35194612Sedclass SourceMgr { 36206274Srdivackypublic: 37234353Sdim enum DiagKind { 38234353Sdim DK_Error, 39234353Sdim DK_Warning, 40234353Sdim DK_Note 41234353Sdim }; 42263508Sdim 43206274Srdivacky /// DiagHandlerTy - Clients that want to handle their own diagnostics in a 44206274Srdivacky /// custom way can register a function pointer+context as a diagnostic 45206274Srdivacky /// handler. It gets called each time PrintMessage is invoked. 46234353Sdim typedef void (*DiagHandlerTy)(const SMDiagnostic &, void *Context); 47206274Srdivackyprivate: 48194612Sed struct SrcBuffer { 49194612Sed /// Buffer - The memory buffer for the file. 50194612Sed MemoryBuffer *Buffer; 51203954Srdivacky 52194612Sed /// IncludeLoc - This is the location of the parent include, or null if at 53194612Sed /// the top level. 54194612Sed SMLoc IncludeLoc; 55194612Sed }; 56203954Srdivacky 57194612Sed /// Buffers - This is all of the buffers that we are reading from. 58194612Sed std::vector<SrcBuffer> Buffers; 59203954Srdivacky 60194612Sed // IncludeDirectories - This is the list of directories we should search for 61194612Sed // include files in. 62194612Sed std::vector<std::string> IncludeDirectories; 63203954Srdivacky 64198090Srdivacky /// LineNoCache - This is a cache for line number queries, its implementation 65198090Srdivacky /// is really private to SourceMgr.cpp. 66198090Srdivacky mutable void *LineNoCache; 67203954Srdivacky 68206274Srdivacky DiagHandlerTy DiagHandler; 69206274Srdivacky void *DiagContext; 70243830Sdim 71243830Sdim SourceMgr(const SourceMgr&) LLVM_DELETED_FUNCTION; 72243830Sdim void operator=(const SourceMgr&) LLVM_DELETED_FUNCTION; 73194612Sedpublic: 74206274Srdivacky SourceMgr() : LineNoCache(0), DiagHandler(0), DiagContext(0) {} 75194612Sed ~SourceMgr(); 76203954Srdivacky 77194612Sed void setIncludeDirs(const std::vector<std::string> &Dirs) { 78194612Sed IncludeDirectories = Dirs; 79194612Sed } 80203954Srdivacky 81206274Srdivacky /// setDiagHandler - Specify a diagnostic handler to be invoked every time 82218893Sdim /// PrintMessage is called. Ctx is passed into the handler when it is invoked. 83218893Sdim void setDiagHandler(DiagHandlerTy DH, void *Ctx = 0) { 84206274Srdivacky DiagHandler = DH; 85206274Srdivacky DiagContext = Ctx; 86206274Srdivacky } 87206274Srdivacky 88226633Sdim DiagHandlerTy getDiagHandler() const { return DiagHandler; } 89226633Sdim void *getDiagContext() const { return DiagContext; } 90226633Sdim 91194612Sed const SrcBuffer &getBufferInfo(unsigned i) const { 92194612Sed assert(i < Buffers.size() && "Invalid Buffer ID!"); 93194612Sed return Buffers[i]; 94194612Sed } 95194612Sed 96194612Sed const MemoryBuffer *getMemoryBuffer(unsigned i) const { 97194612Sed assert(i < Buffers.size() && "Invalid Buffer ID!"); 98194612Sed return Buffers[i].Buffer; 99194612Sed } 100203954Srdivacky 101263508Sdim size_t getNumBuffers() const { 102249423Sdim return Buffers.size(); 103249423Sdim } 104249423Sdim 105194612Sed SMLoc getParentIncludeLoc(unsigned i) const { 106194612Sed assert(i < Buffers.size() && "Invalid Buffer ID!"); 107194612Sed return Buffers[i].IncludeLoc; 108194612Sed } 109203954Srdivacky 110206274Srdivacky /// AddNewSourceBuffer - Add a new source buffer to this source manager. This 111206274Srdivacky /// takes ownership of the memory buffer. 112263508Sdim size_t AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) { 113194612Sed SrcBuffer NB; 114194612Sed NB.Buffer = F; 115194612Sed NB.IncludeLoc = IncludeLoc; 116194612Sed Buffers.push_back(NB); 117263508Sdim return Buffers.size() - 1; 118194612Sed } 119203954Srdivacky 120194612Sed /// AddIncludeFile - Search for a file with the specified name in the current 121194612Sed /// directory or in one of the IncludeDirs. If no file is found, this returns 122194612Sed /// ~0, otherwise it returns the buffer ID of the stacked file. 123223017Sdim /// The full path to the included file can be found in IncludedFile. 124263508Sdim size_t AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, 125263508Sdim std::string &IncludedFile); 126203954Srdivacky 127194612Sed /// FindBufferContainingLoc - Return the ID of the buffer containing the 128194612Sed /// specified location, returning -1 if not found. 129194612Sed int FindBufferContainingLoc(SMLoc Loc) const; 130203954Srdivacky 131194612Sed /// FindLineNumber - Find the line number for the specified location in the 132194612Sed /// specified file. This is not a fast method. 133239462Sdim unsigned FindLineNumber(SMLoc Loc, int BufferID = -1) const { 134239462Sdim return getLineAndColumn(Loc, BufferID).first; 135239462Sdim } 136203954Srdivacky 137239462Sdim /// getLineAndColumn - Find the line and column number for the specified 138239462Sdim /// location in the specified file. This is not a fast method. 139239462Sdim std::pair<unsigned, unsigned> 140239462Sdim getLineAndColumn(SMLoc Loc, int BufferID = -1) const; 141239462Sdim 142194612Sed /// PrintMessage - Emit a message about the specified location with the 143194612Sed /// specified string. 144195340Sed /// 145234982Sdim /// @param ShowColors - Display colored messages if output is a terminal and 146234982Sdim /// the default error handler is used. 147263508Sdim void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, 148263508Sdim const Twine &Msg, 149263508Sdim ArrayRef<SMRange> Ranges = None, 150263508Sdim ArrayRef<SMFixIt> FixIts = None, 151263508Sdim bool ShowColors = true) const; 152263508Sdim 153263508Sdim /// Emits a diagnostic to llvm::errs(). 154234353Sdim void PrintMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, 155251662Sdim ArrayRef<SMRange> Ranges = None, 156251662Sdim ArrayRef<SMFixIt> FixIts = None, 157234982Sdim bool ShowColors = true) const; 158203954Srdivacky 159195340Sed /// GetMessage - Return an SMDiagnostic at the specified location with the 160195340Sed /// specified string. 161195340Sed /// 162243830Sdim /// @param Msg If non-null, the kind of message (e.g., "error") which is 163195340Sed /// prefixed to the message. 164251662Sdim SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, 165251662Sdim ArrayRef<SMRange> Ranges = None, 166251662Sdim ArrayRef<SMFixIt> FixIts = None) const; 167203954Srdivacky 168226633Sdim /// PrintIncludeStack - Prints the names of included files and the line of the 169226633Sdim /// file they were included from. A diagnostic handler can use this before 170226633Sdim /// printing its custom formatted message. 171226633Sdim /// 172226633Sdim /// @param IncludeLoc - The line of the include. 173226633Sdim /// @param OS the raw_ostream to print on. 174195340Sed void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const; 175194612Sed}; 176195340Sed 177203954Srdivacky 178249423Sdim/// Represents a single fixit, a replacement of one range of text with another. 179249423Sdimclass SMFixIt { 180249423Sdim SMRange Range; 181249423Sdim 182249423Sdim std::string Text; 183249423Sdim 184249423Sdimpublic: 185249423Sdim // FIXME: Twine.str() is not very efficient. 186249423Sdim SMFixIt(SMLoc Loc, const Twine &Insertion) 187249423Sdim : Range(Loc, Loc), Text(Insertion.str()) { 188249423Sdim assert(Loc.isValid()); 189249423Sdim } 190249423Sdim 191249423Sdim // FIXME: Twine.str() is not very efficient. 192249423Sdim SMFixIt(SMRange R, const Twine &Replacement) 193249423Sdim : Range(R), Text(Replacement.str()) { 194249423Sdim assert(R.isValid()); 195249423Sdim } 196249423Sdim 197249423Sdim StringRef getText() const { return Text; } 198249423Sdim SMRange getRange() const { return Range; } 199249423Sdim 200249423Sdim bool operator<(const SMFixIt &Other) const { 201249423Sdim if (Range.Start.getPointer() != Other.Range.Start.getPointer()) 202249423Sdim return Range.Start.getPointer() < Other.Range.Start.getPointer(); 203249423Sdim if (Range.End.getPointer() != Other.Range.End.getPointer()) 204249423Sdim return Range.End.getPointer() < Other.Range.End.getPointer(); 205249423Sdim return Text < Other.Text; 206249423Sdim } 207249423Sdim}; 208249423Sdim 209249423Sdim 210195340Sed/// SMDiagnostic - Instances of this class encapsulate one diagnostic report, 211195340Sed/// allowing printing to a raw_ostream as a caret diagnostic. 212195340Sedclass SMDiagnostic { 213207618Srdivacky const SourceMgr *SM; 214206274Srdivacky SMLoc Loc; 215195340Sed std::string Filename; 216195340Sed int LineNo, ColumnNo; 217234353Sdim SourceMgr::DiagKind Kind; 218195340Sed std::string Message, LineContents; 219234353Sdim std::vector<std::pair<unsigned, unsigned> > Ranges; 220249423Sdim SmallVector<SMFixIt, 4> FixIts; 221199989Srdivacky 222195340Sedpublic: 223207618Srdivacky // Null diagnostic. 224234353Sdim SMDiagnostic() 225234353Sdim : SM(0), LineNo(0), ColumnNo(0), Kind(SourceMgr::DK_Error) {} 226207618Srdivacky // Diagnostic with no location (e.g. file not found, command line arg error). 227249423Sdim SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg) 228239462Sdim : SM(0), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), 229234353Sdim Message(Msg) {} 230263508Sdim 231207618Srdivacky // Diagnostic with a location. 232249423Sdim SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN, 233234353Sdim int Line, int Col, SourceMgr::DiagKind Kind, 234249423Sdim StringRef Msg, StringRef LineStr, 235249423Sdim ArrayRef<std::pair<unsigned,unsigned> > Ranges, 236251662Sdim ArrayRef<SMFixIt> FixIts = None); 237195340Sed 238207618Srdivacky const SourceMgr *getSourceMgr() const { return SM; } 239206274Srdivacky SMLoc getLoc() const { return Loc; } 240249423Sdim StringRef getFilename() const { return Filename; } 241206274Srdivacky int getLineNo() const { return LineNo; } 242206274Srdivacky int getColumnNo() const { return ColumnNo; } 243234353Sdim SourceMgr::DiagKind getKind() const { return Kind; } 244249423Sdim StringRef getMessage() const { return Message; } 245249423Sdim StringRef getLineContents() const { return LineContents; } 246249423Sdim ArrayRef<std::pair<unsigned, unsigned> > getRanges() const { 247234353Sdim return Ranges; 248234353Sdim } 249249423Sdim 250249423Sdim void addFixIt(const SMFixIt &Hint) { 251249423Sdim FixIts.push_back(Hint); 252249423Sdim } 253249423Sdim 254249423Sdim ArrayRef<SMFixIt> getFixIts() const { 255249423Sdim return FixIts; 256249423Sdim } 257249423Sdim 258249423Sdim void print(const char *ProgName, raw_ostream &S, 259249423Sdim bool ShowColors = true) const; 260195340Sed}; 261203954Srdivacky 262194612Sed} // end llvm namespace 263194612Sed 264194612Sed#endif 265