1
//===- SourceMgr.h - Manager for Source Buffers & Diagnostics ---*- C++ -*-===//
3
// The LLVM Compiler Infrastructure
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
8
//===----------------------------------------------------------------------===//
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.
14
//===----------------------------------------------------------------------===//
16
#ifndef LLVM_SUPPORT_SOURCEMGR_H
17
#define LLVM_SUPPORT_SOURCEMGR_H
19
#include "llvm/ADT/ArrayRef.h"
20
#include "llvm/ADT/StringRef.h"
21
#include "llvm/ADT/Twine.h"
22
#include "llvm/Support/MemoryBuffer.h"
23
#include "llvm/Support/SMLoc.h"
33
/// This owns the files read by a parser, handles include stacks,
34
/// and handles diagnostic wrangling.
43
/// Clients that want to handle their own diagnostics in a custom way can
44
/// register a function pointer+context as a diagnostic handler.
45
/// It gets called each time PrintMessage is invoked.
46
typedef void (*DiagHandlerTy)(const SMDiagnostic &, void *Context);
49
/// The memory buffer for the file.
50
std::unique_ptr<MemoryBuffer> Buffer;
52
/// This is the location of the parent include, or null if at the top level.
57
SrcBuffer(SrcBuffer &&O)
58
: Buffer(std::move(O.Buffer)), IncludeLoc(O.IncludeLoc) {}
61
/// This is all of the buffers that we are reading from.
62
std::vector<SrcBuffer> Buffers;
64
// This is the list of directories we should search for include files in.
65
std::vector<std::string> IncludeDirectories;
67
/// This is a cache for line number queries, its implementation is really
68
/// private to SourceMgr.cpp.
69
mutable void *LineNoCache;
71
DiagHandlerTy DiagHandler;
74
bool isValidBufferID(unsigned i) const { return i && i <= Buffers.size(); }
76
SourceMgr(const SourceMgr&) = delete;
77
void operator=(const SourceMgr&) = delete;
80
: LineNoCache(nullptr), DiagHandler(nullptr), DiagContext(nullptr) {}
83
void setIncludeDirs(const std::vector<std::string> &Dirs) {
84
IncludeDirectories = Dirs;
87
/// Specify a diagnostic handler to be invoked every time PrintMessage is
88
/// called. \p Ctx is passed into the handler when it is invoked.
89
void setDiagHandler(DiagHandlerTy DH, void *Ctx = nullptr) {
94
DiagHandlerTy getDiagHandler() const { return DiagHandler; }
95
void *getDiagContext() const { return DiagContext; }
97
const SrcBuffer &getBufferInfo(unsigned i) const {
98
assert(isValidBufferID(i));
99
return Buffers[i - 1];
102
const MemoryBuffer *getMemoryBuffer(unsigned i) const {
103
assert(isValidBufferID(i));
104
return Buffers[i - 1].Buffer.get();
107
unsigned getNumBuffers() const {
108
return Buffers.size();
111
unsigned getMainFileID() const {
112
assert(getNumBuffers());
116
SMLoc getParentIncludeLoc(unsigned i) const {
117
assert(isValidBufferID(i));
118
return Buffers[i - 1].IncludeLoc;
121
/// Add a new source buffer to this source manager. This takes ownership of
122
/// the memory buffer.
123
unsigned AddNewSourceBuffer(std::unique_ptr<MemoryBuffer> F,
126
NB.Buffer = std::move(F);
127
NB.IncludeLoc = IncludeLoc;
128
Buffers.push_back(std::move(NB));
129
return Buffers.size();
132
/// Search for a file with the specified name in the current directory or in
133
/// one of the IncludeDirs.
135
/// If no file is found, this returns 0, otherwise it returns the buffer ID
136
/// of the stacked file. The full path to the included file can be found in
138
unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc,
139
std::string &IncludedFile);
141
/// Return the ID of the buffer containing the specified location.
143
/// 0 is returned if the buffer is not found.
144
unsigned FindBufferContainingLoc(SMLoc Loc) const;
146
/// Find the line number for the specified location in the specified file.
147
/// This is not a fast method.
148
unsigned FindLineNumber(SMLoc Loc, unsigned BufferID = 0) const {
149
return getLineAndColumn(Loc, BufferID).first;
152
/// Find the line and column number for the specified location in the
153
/// specified file. This is not a fast method.
154
std::pair<unsigned, unsigned> getLineAndColumn(SMLoc Loc,
155
unsigned BufferID = 0) const;
157
/// Emit a message about the specified location with the specified string.
159
/// \param ShowColors Display colored messages if output is a terminal and
160
/// the default error handler is used.
161
void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind,
163
ArrayRef<SMRange> Ranges = None,
164
ArrayRef<SMFixIt> FixIts = None,
165
bool ShowColors = true) const;
167
/// Emits a diagnostic to llvm::errs().
168
void PrintMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg,
169
ArrayRef<SMRange> Ranges = None,
170
ArrayRef<SMFixIt> FixIts = None,
171
bool ShowColors = true) const;
173
/// Emits a manually-constructed diagnostic to the given output stream.
175
/// \param ShowColors Display colored messages if output is a terminal and
176
/// the default error handler is used.
177
void PrintMessage(raw_ostream &OS, const SMDiagnostic &Diagnostic,
178
bool ShowColors = true) const;
180
/// Return an SMDiagnostic at the specified location with the specified
183
/// \param Msg If non-null, the kind of message (e.g., "error") which is
184
/// prefixed to the message.
185
SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg,
186
ArrayRef<SMRange> Ranges = None,
187
ArrayRef<SMFixIt> FixIts = None) const;
189
/// Prints the names of included files and the line of the file they were
190
/// included from. A diagnostic handler can use this before printing its
191
/// custom formatted message.
193
/// \param IncludeLoc The location of the include.
194
/// \param OS the raw_ostream to print on.
195
void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const;
199
/// Represents a single fixit, a replacement of one range of text with another.
206
// FIXME: Twine.str() is not very efficient.
207
SMFixIt(SMLoc Loc, const Twine &Insertion)
208
: Range(Loc, Loc), Text(Insertion.str()) {
209
assert(Loc.isValid());
212
// FIXME: Twine.str() is not very efficient.
213
SMFixIt(SMRange R, const Twine &Replacement)
214
: Range(R), Text(Replacement.str()) {
218
StringRef getText() const { return Text; }
219
SMRange getRange() const { return Range; }
221
bool operator<(const SMFixIt &Other) const {
222
if (Range.Start.getPointer() != Other.Range.Start.getPointer())
223
return Range.Start.getPointer() < Other.Range.Start.getPointer();
224
if (Range.End.getPointer() != Other.Range.End.getPointer())
225
return Range.End.getPointer() < Other.Range.End.getPointer();
226
return Text < Other.Text;
231
/// Instances of this class encapsulate one diagnostic report, allowing
232
/// printing to a raw_ostream as a caret diagnostic.
236
std::string Filename;
237
int LineNo, ColumnNo;
238
SourceMgr::DiagKind Kind;
239
std::string Message, LineContents;
240
std::vector<std::pair<unsigned, unsigned> > Ranges;
241
SmallVector<SMFixIt, 4> FixIts;
246
: SM(nullptr), LineNo(0), ColumnNo(0), Kind(SourceMgr::DK_Error) {}
247
// Diagnostic with no location (e.g. file not found, command line arg error).
248
SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg)
249
: SM(nullptr), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd),
252
// Diagnostic with a location.
253
SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN,
254
int Line, int Col, SourceMgr::DiagKind Kind,
255
StringRef Msg, StringRef LineStr,
256
ArrayRef<std::pair<unsigned,unsigned> > Ranges,
257
ArrayRef<SMFixIt> FixIts = None);
259
const SourceMgr *getSourceMgr() const { return SM; }
260
SMLoc getLoc() const { return Loc; }
261
StringRef getFilename() const { return Filename; }
262
int getLineNo() const { return LineNo; }
263
int getColumnNo() const { return ColumnNo; }
264
SourceMgr::DiagKind getKind() const { return Kind; }
265
StringRef getMessage() const { return Message; }
266
StringRef getLineContents() const { return LineContents; }
267
ArrayRef<std::pair<unsigned, unsigned> > getRanges() const {
271
void addFixIt(const SMFixIt &Hint) {
272
FixIts.push_back(Hint);
275
ArrayRef<SMFixIt> getFixIts() const {
279
void print(const char *ProgName, raw_ostream &S, bool ShowColors = true,
280
bool ShowKindLabel = true) const;
283
} // end llvm namespace