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