LLVM: lib/Support/SourceMgr.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
29#include
30#include
31#include
32#include
33#include
34#include
35#include
36
37using namespace llvm;
38
40
43 std::string &IncludedFile) {
46 if (!NewBufOrErr)
47 return 0;
48
50}
51
54 std::string &IncludedFile) {
57
59
60 for (unsigned i = 0, e = IncludeDirectories.size(); i != e && !NewBufOrErr;
61 ++i) {
62 Buffer = IncludeDirectories[i];
65 }
66
67 if (NewBufOrErr)
68 IncludedFile = static_caststd::string\(Buffer);
69
70 return NewBufOrErr;
71}
72
74 for (unsigned i = 0, e = Buffers.size(); i != e; ++i)
75 if (Loc.getPointer() >= Buffers[i].Buffer->getBufferStart() &&
76
77
78 Loc.getPointer() <= Buffers[i].Buffer->getBufferEnd())
79 return i + 1;
80 return 0;
81}
82
83template
86 if (OffsetCache)
87 return *static_cast<std::vector *>(OffsetCache);
88
89
90 auto *Offsets = new std::vector();
92 assert(Sz <= std::numeric_limits::max());
94 for (size_t N = 0; N < Sz; ++N) {
95 if (S[N] == '\n')
96 Offsets->push_back(static_cast<T>(N));
97 }
98
99 OffsetCache = Offsets;
100 return *Offsets;
101}
102
103template
104unsigned SourceMgr::SrcBuffer::getLineNumberSpecialized(const char *Ptr) const {
105 std::vector &Offsets =
106 GetOrCreateOffsetCache(OffsetCache, Buffer.get());
107
108 const char *BufStart = Buffer->getBufferStart();
109 assert(Ptr >= BufStart && Ptr <= Buffer->getBufferEnd());
111 assert(PtrDiff >= 0 &&
112 static_cast<size_t>(PtrDiff) <= std::numeric_limits::max());
113 T PtrOffset = static_cast<T>(PtrDiff);
114
115
116
118}
119
120
121
122unsigned SourceMgr::SrcBuffer::getLineNumber(const char *Ptr) const {
123 size_t Sz = Buffer->getBufferSize();
124 if (Sz <= std::numeric_limits<uint8_t>::max())
125 return getLineNumberSpecialized<uint8_t>(Ptr);
126 else if (Sz <= std::numeric_limits<uint16_t>::max())
127 return getLineNumberSpecialized<uint16_t>(Ptr);
128 else if (Sz <= std::numeric_limits<uint32_t>::max())
129 return getLineNumberSpecialized<uint32_t>(Ptr);
130 else
131 return getLineNumberSpecialized<uint64_t>(Ptr);
132}
133
134template
135const char *SourceMgr::SrcBuffer::getPointerForLineNumberSpecialized(
136 unsigned LineNo) const {
137 std::vector &Offsets =
138 GetOrCreateOffsetCache(OffsetCache, Buffer.get());
139
140
141 if (LineNo != 0)
142 --LineNo;
143
144 const char *BufStart = Buffer->getBufferStart();
145
146
147
148 if (LineNo == 0)
149 return BufStart;
150 if (LineNo > Offsets.size())
151 return nullptr;
152 return BufStart + Offsets[LineNo - 1] + 1;
153}
154
155
156
157const char *
158SourceMgr::SrcBuffer::getPointerForLineNumber(unsigned LineNo) const {
159 size_t Sz = Buffer->getBufferSize();
160 if (Sz <= std::numeric_limits<uint8_t>::max())
161 return getPointerForLineNumberSpecialized<uint8_t>(LineNo);
162 else if (Sz <= std::numeric_limits<uint16_t>::max())
163 return getPointerForLineNumberSpecialized<uint16_t>(LineNo);
164 else if (Sz <= std::numeric_limits<uint32_t>::max())
165 return getPointerForLineNumberSpecialized<uint32_t>(LineNo);
166 else
167 return getPointerForLineNumberSpecialized<uint64_t>(LineNo);
168}
169
170SourceMgr::SrcBuffer::SrcBuffer(SourceMgr::SrcBuffer &&Other)
171 : Buffer(std::move(Other.Buffer)), OffsetCache(Other.OffsetCache),
172 IncludeLoc(Other.IncludeLoc) {
173 Other.OffsetCache = nullptr;
174}
175
176SourceMgr::SrcBuffer::~SrcBuffer() {
177 if (OffsetCache) {
178 size_t Sz = Buffer->getBufferSize();
179 if (Sz <= std::numeric_limits<uint8_t>::max())
180 delete static_cast<std::vector<uint8_t> *>(OffsetCache);
181 else if (Sz <= std::numeric_limits<uint16_t>::max())
182 delete static_cast<std::vector<uint16_t> *>(OffsetCache);
183 else if (Sz <= std::numeric_limits<uint32_t>::max())
184 delete static_cast<std::vector<uint32_t> *>(OffsetCache);
185 else
186 delete static_cast<std::vector<uint64_t> *>(OffsetCache);
187 OffsetCache = nullptr;
188 }
189}
190
191std::pair<unsigned, unsigned>
193 if (!BufferID)
195 assert(BufferID && "Invalid location!");
196
199
200 unsigned LineNo = SB.getLineNumber(Ptr);
201 const char *BufStart = SB.Buffer->getBufferStart();
204 NewlineOffs = ~(size_t)0;
205 return std::make_pair(LineNo, Ptr - BufStart - NewlineOffs);
206}
207
208
209
210
211
212
213
214
215
217 bool IncludePath) const {
219 assert(BufferID && "Invalid location!");
220 auto FileSpec = getBufferInfo(BufferID).Buffer->getBufferIdentifier();
221
222 if (IncludePath) {
223 return FileSpec.str() + ":" + std::to_string(FindLineNumber(Loc, BufferID));
224 } else {
225 auto I = FileSpec.find_last_of("/\\");
226 I = (I == FileSpec.size()) ? 0 : (I + 1);
227 return FileSpec.substr(I).str() + ":" +
229 }
230}
231
232
233
235 unsigned ColNo) {
237 const char *Ptr = SB.getPointerForLineNumber(LineNo);
238 if ()
240
241
242 if (ColNo != 0)
243 --ColNo;
244
245
246 if (ColNo) {
247
248 if (Ptr + ColNo > SB.Buffer->getBufferEnd())
250
251
254
255 Ptr += ColNo;
256 }
257
259}
260
262 if (IncludeLoc == SMLoc())
263 return;
264
266 assert(CurBuf && "Invalid or unspecified location!");
267
269
270 OS << "Included from " << getBufferInfo(CurBuf).Buffer->getBufferIdentifier()
271 << ":" << FindLineNumber(IncludeLoc, CurBuf) << ":\n";
272}
273
277
278
280 std::pair<unsigned, unsigned> LineAndCol;
281 StringRef BufferID = "";
283
286 assert(CurBuf && "Invalid or unspecified location!");
287
290
291
292 const char *LineStart = Loc.getPointer();
294 while (LineStart != BufStart && LineStart[-1] != '\n' &&
295 LineStart[-1] != '\r')
296 --LineStart;
297
298
299 const char *LineEnd = Loc.getPointer();
301 while (LineEnd != BufEnd && LineEnd[0] != '\n' && LineEnd[0] != '\r')
302 ++LineEnd;
303 LineStr = StringRef(LineStart, LineEnd - LineStart);
304
305
306
307 for (SMRange R : Ranges) {
308 if (!R.isValid())
309 continue;
310
311
312 if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart)
313 continue;
314
315
316 if (R.Start.getPointer() < LineStart)
318 if (R.End.getPointer() > LineEnd)
320
321
322
323 ColRanges.push_back(std::make_pair(R.Start.getPointer() - LineStart,
324 R.End.getPointer() - LineStart));
325 }
326
328 }
329
330 return SMDiagnostic(*this, Loc, BufferID, LineAndCol.first,
331 LineAndCol.second - 1, Kind, Msg.str(), LineStr,
332 ColRanges, FixIts);
333}
334
336 bool ShowColors) const {
337
338 if (DiagHandler) {
339 DiagHandler(Diagnostic, DiagContext);
340 return;
341 }
342
345 assert(CurBuf && "Invalid or unspecified location!");
347 }
348
349 Diagnostic.print(nullptr, OS, ShowColors);
350}
351
355 bool ShowColors) const {
357}
358
362 PrintMessage(errs(), Loc, Kind, Msg, Ranges, FixIts, ShowColors);
363}
364
365
366
367
368
370 : Range(R), Text(Replacement.str()) {
372}
373
374
375
376
377
381 ArrayRef<std::pair<unsigned, unsigned>> Ranges,
383 : SM(&sm), Loc(L), Filename(std::string(FN)), LineNo(Line), ColumnNo(Col),
384 Kind(Kind), Message(Msg), LineContents(LineStr), Ranges(Ranges.vec()),
385 FixIts(Hints) {
387}
388
389static void buildFixItLine(std::string &CaretLine, std::string &FixItLine,
392 if (FixIts.empty())
393 return;
394
395 const char *LineStart = SourceLine.begin();
396 const char *LineEnd = SourceLine.end();
397
398 size_t PrevHintEndCol = 0;
399
401
402 if (Fixit.getText().find_first_of("\n\r\t") != StringRef::npos)
403 continue;
404
405 SMRange R = Fixit.getRange();
406
407
408 if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart)
409 continue;
410
411
412
413
414 unsigned FirstCol;
415 if (R.Start.getPointer() < LineStart)
416 FirstCol = 0;
417 else
418 FirstCol = R.Start.getPointer() - LineStart;
419
420
421
422
423
424
425
426
427 unsigned HintCol = FirstCol;
428 if (HintCol < PrevHintEndCol)
429 HintCol = PrevHintEndCol + 1;
430
431
432
433
435 Fixit.getText().size());
436
437
438 unsigned LastColumnModified = HintCol + Fixit.getText().size();
439 if (LastColumnModified > FixItLine.size())
440 FixItLine.resize(LastColumnModified, ' ');
441
442 llvm::copy(Fixit.getText(), FixItLine.begin() + HintCol);
443
444 PrevHintEndCol = LastColumnModified;
445
446
447
448 unsigned LastCol;
449 if (R.End.getPointer() >= LineEnd)
450 LastCol = LineEnd - LineStart;
451 else
452 LastCol = R.End.getPointer() - LineStart;
453
454 std::fill(&CaretLine[FirstCol], &CaretLine[LastCol], '~');
455 }
456}
457
459
460 for (unsigned i = 0, e = LineContents.size(), OutCol = 0; i != e; ++i) {
461 size_t NextTab = LineContents.find('\t', i);
462
465 break;
466 }
467
468
469 S << LineContents.slice(i, NextTab);
470 OutCol += NextTab - i;
471 i = NextTab;
472
473
474 do {
475 S << ' ';
476 ++OutCol;
477 } while ((OutCol % TabStop) != 0);
478 }
479 S << '\n';
480}
481
482static bool isNonASCII(char c) { return c & 0x80; }
483
485 bool ShowKindLabel, bool ShowLocation) const {
487
488 {
490
491 if (ProgName && ProgName[0])
492 S << ProgName << ": ";
493
494 if (ShowLocation && !Filename.empty()) {
495 if (Filename == "-")
496 S << "";
497 else
498 S << Filename;
499
500 if (LineNo != -1) {
501 S << ':' << LineNo;
502 if (ColumnNo != -1)
503 S << ':' << (ColumnNo + 1);
504 }
505 S << ": ";
506 }
507 }
508
509 if (ShowKindLabel) {
510 switch (Kind) {
513 break;
516 break;
519 break;
522 break;
523 }
524 }
525
527
528 if (LineNo == -1 || ColumnNo == -1)
529 return;
530
531
532
533
534
535
538 return;
539 }
540 size_t NumColumns = LineContents.size();
541
542
543 std::string CaretLine(NumColumns + 1, ' ');
544
545
546 for (const std::pair<unsigned, unsigned> &R : Ranges)
547 std::fill(&CaretLine[R.first],
548 &CaretLine[std::min((size_t)R.second, CaretLine.size())], '~');
549
550
551
552 std::string FixItInsertionLine;
553 buildFixItLine(CaretLine, FixItInsertionLine, FixIts,
555
556
557 if (unsigned(ColumnNo) <= NumColumns)
558 CaretLine[ColumnNo] = '^';
559 else
560 CaretLine[NumColumns] = '^';
561
562
563
564
565 CaretLine.erase(CaretLine.find_last_not_of(' ') + 1);
566
568
569 {
572
573
574 for (unsigned i = 0, e = CaretLine.size(), OutCol = 0; i != e; ++i) {
575 if (i >= LineContents.size() || LineContents[i] != '\t') {
576 S << CaretLine[i];
577 ++OutCol;
578 continue;
579 }
580
581
582 do {
583 S << CaretLine[i];
584 ++OutCol;
585 } while ((OutCol % TabStop) != 0);
586 }
587 S << '\n';
588 }
589
590
591 if (FixItInsertionLine.empty())
592 return;
593
594 for (size_t i = 0, e = FixItInsertionLine.size(), OutCol = 0; i < e; ++i) {
595 if (i >= LineContents.size() || LineContents[i] != '\t') {
596 OS << FixItInsertionLine[i];
597 ++OutCol;
598 continue;
599 }
600
601
602 do {
603 OS << FixItInsertionLine[i];
604
605
606
607
608
609 if (FixItInsertionLine[i] != ' ')
610 ++i;
611 ++OutCol;
612 } while (((OutCol % TabStop) != 0) && i != e);
613 }
614 OS << '\n';
615}
std::optional< std::vector< StOtherPiece > > Other
Provides ErrorOr smart pointer.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallString class.
This file defines the SmallVector class.
static const size_t TabStop
static bool isNonASCII(char c)
static void buildFixItLine(std::string &CaretLine, std::string &FixItLine, ArrayRef< SMFixIt > FixIts, ArrayRef< char > SourceLine)
static void printSourceLine(raw_ostream &S, StringRef LineContents)
static std::vector< T > & GetOrCreateOffsetCache(void *&OffsetCache, MemoryBuffer *Buffer)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
empty - Check if the array is empty.
Represents either an error or a value T.
This interface provides simple read-only access to a block of memory, and provides simple methods for...
virtual StringRef getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
size_t getBufferSize() const
StringRef getBuffer() const
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
const char * getBufferEnd() const
const char * getBufferStart() const
Instances of this class encapsulate one diagnostic report, allowing printing to a raw_ostream as a ca...
void print(const char *ProgName, raw_ostream &S, bool ShowColors=true, bool ShowKindLabel=true, bool ShowLocation=true) const
Represents a single fixit, a replacement of one range of text with another.
SMFixIt(SMRange R, const Twine &Replacement)
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
constexpr const char * getPointer() const
constexpr bool isValid() const
Represents a range in source code.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
ErrorOr< std::unique_ptr< MemoryBuffer > > OpenIncludeFile(const std::string &Filename, std::string &IncludedFile)
Search for a file with the specified name in the current directory or in one of the IncludeDirs,...
std::pair< unsigned, unsigned > getLineAndColumn(SMLoc Loc, unsigned BufferID=0) const
Find the line and column number for the specified location in the specified file.
const MemoryBuffer * getMemoryBuffer(unsigned i) const
void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const
Prints the names of included files and the line of the file they were included from.
unsigned FindBufferContainingLoc(SMLoc Loc) const
Return the ID of the buffer containing the specified location.
SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}) const
Return an SMDiagnostic at the specified location with the specified string.
unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, std::string &IncludedFile)
Search for a file with the specified name in the current directory or in one of the IncludeDirs.
unsigned FindLineNumber(SMLoc Loc, unsigned BufferID=0) const
Find the line number for the specified location in the specified file.
std::string getFormattedLocationNoOffset(SMLoc Loc, bool IncludePath=false) const
Get a string with the SMLoc filename and line number formatted in the standard style.
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
SMLoc FindLocForLineAndColumn(unsigned BufferID, unsigned LineNo, unsigned ColNo)
Given a line and column number in a mapped buffer, turn it into an SMLoc.
const SrcBuffer & getBufferInfo(unsigned i) const
StringRef - Represent a constant reference to a string, i.e.
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
size - Get the string size.
size_t find_last_of(char C, size_t From=npos) const
Find the last character in the string that is C, or npos if not found.
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
static constexpr size_t npos
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
std::string str() const
Return the twine contents as a std::string.
An RAII object that temporarily switches an output stream to a specific color.
static raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
static raw_ostream & error()
Convenience method for printing "error: " to stderr.
static raw_ostream & note()
Convenience method for printing "note: " to stderr.
static raw_ostream & remark()
Convenience method for printing "remark: " to stderr.
This class implements an extremely fast bulk output stream that can only output to a stream.
static constexpr Colors SAVEDCOLOR
static constexpr Colors GREEN
Offsets
Offsets in bytes from the start of the input buffer.
int columnWidth(StringRef s)
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
This is an optimization pass for GlobalISel generic memory operations.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
void sort(IteratorTy Start, IteratorTy End)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
OutputIt copy(R &&Range, OutputIt Out)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
@ Auto
Determine whether to use color based on the command line argument and the raw_ostream.
Implement std::hash so that hash_code can be used in STL containers.