LLVM: lib/Support/SourceMgr.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
30#include
31#include
32#include
33#include
34#include
35#include
36#include
37
38using namespace llvm;
39
41
42
49
53
55 this->FS = std::move(FS);
56}
57
60 std::string &IncludedFile) {
63 if (!NewBufOrErr)
64 return 0;
65
67}
68
71 std::string &IncludedFile) {
72 auto GetFile = [this](StringRef Path) {
74 };
75
77
79
80 for (unsigned i = 0, e = IncludeDirectories.size(); i != e && !NewBufOrErr;
81 ++i) {
82 Buffer = IncludeDirectories[i];
84 NewBufOrErr = GetFile(Buffer);
85 }
86
87 if (NewBufOrErr)
88 IncludedFile = static_caststd::string\(Buffer);
89
90 return NewBufOrErr;
91}
92
94 for (unsigned i = 0, e = Buffers.size(); i != e; ++i)
95 if (Loc.getPointer() >= Buffers[i].Buffer->getBufferStart() &&
96
97
98 Loc.getPointer() <= Buffers[i].Buffer->getBufferEnd())
99 return i + 1;
100 return 0;
101}
102
103template
106 if (OffsetCache)
107 return *static_cast<std::vector *>(OffsetCache);
108
109
110 auto *Offsets = new std::vector();
112 assert(Sz <= std::numeric_limits::max());
114 for (size_t N = 0; N < Sz; ++N) {
115 if (S[N] == '\n')
116 Offsets->push_back(static_cast<T>(N));
117 }
118
119 OffsetCache = Offsets;
120 return *Offsets;
121}
122
123template
124unsigned SourceMgr::SrcBuffer::getLineNumberSpecialized(const char *Ptr) const {
125 std::vector &Offsets =
127
128 const char *BufStart = Buffer->getBufferStart();
129 assert(Ptr >= BufStart && Ptr <= Buffer->getBufferEnd());
130 ptrdiff_t PtrDiff = Ptr - BufStart;
131 assert(PtrDiff >= 0 &&
132 static_cast<size_t>(PtrDiff) <= std::numeric_limits::max());
133 T PtrOffset = static_cast<T>(PtrDiff);
134
135
136
138}
139
140
141
142unsigned SourceMgr::SrcBuffer::getLineNumber(const char *Ptr) const {
143 size_t Sz = Buffer->getBufferSize();
144 if (Sz <= std::numeric_limits<uint8_t>::max())
145 return getLineNumberSpecialized<uint8_t>(Ptr);
146 else if (Sz <= std::numeric_limits<uint16_t>::max())
147 return getLineNumberSpecialized<uint16_t>(Ptr);
148 else if (Sz <= std::numeric_limits<uint32_t>::max())
149 return getLineNumberSpecialized<uint32_t>(Ptr);
150 else
151 return getLineNumberSpecialized<uint64_t>(Ptr);
152}
153
154template
155const char *SourceMgr::SrcBuffer::getPointerForLineNumberSpecialized(
156 unsigned LineNo) const {
157 std::vector &Offsets =
159
160
161 if (LineNo != 0)
162 --LineNo;
163
164 const char *BufStart = Buffer->getBufferStart();
165
166
167
168 if (LineNo == 0)
169 return BufStart;
170 if (LineNo > Offsets.size())
171 return nullptr;
172 return BufStart + Offsets[LineNo - 1] + 1;
173}
174
175
176
177const char *
178SourceMgr::SrcBuffer::getPointerForLineNumber(unsigned LineNo) const {
179 size_t Sz = Buffer->getBufferSize();
180 if (Sz <= std::numeric_limits<uint8_t>::max())
181 return getPointerForLineNumberSpecialized<uint8_t>(LineNo);
182 else if (Sz <= std::numeric_limits<uint16_t>::max())
183 return getPointerForLineNumberSpecialized<uint16_t>(LineNo);
184 else if (Sz <= std::numeric_limits<uint32_t>::max())
185 return getPointerForLineNumberSpecialized<uint32_t>(LineNo);
186 else
187 return getPointerForLineNumberSpecialized<uint64_t>(LineNo);
188}
189
190SourceMgr::SrcBuffer::SrcBuffer(SourceMgr::SrcBuffer &&Other)
191 : Buffer(std::move(Other.Buffer)), OffsetCache(Other.OffsetCache),
192 IncludeLoc(Other.IncludeLoc) {
193 Other.OffsetCache = nullptr;
194}
195
196SourceMgr::SrcBuffer::~SrcBuffer() {
197 if (OffsetCache) {
198 size_t Sz = Buffer->getBufferSize();
199 if (Sz <= std::numeric_limits<uint8_t>::max())
200 delete static_cast<std::vector<uint8_t> *>(OffsetCache);
201 else if (Sz <= std::numeric_limits<uint16_t>::max())
202 delete static_cast<std::vector<uint16_t> *>(OffsetCache);
203 else if (Sz <= std::numeric_limits<uint32_t>::max())
204 delete static_cast<std::vector<uint32_t> *>(OffsetCache);
205 else
206 delete static_cast<std::vector<uint64_t> *>(OffsetCache);
207 OffsetCache = nullptr;
208 }
209}
210
211std::pair<unsigned, unsigned>
213 if (!BufferID)
215 assert(BufferID && "Invalid location!");
216
218 const char *Ptr = Loc.getPointer();
219
220 unsigned LineNo = SB.getLineNumber(Ptr);
221 const char *BufStart = SB.Buffer->getBufferStart();
224 NewlineOffs = ~(size_t)0;
225 return {LineNo, Ptr - BufStart - NewlineOffs};
226}
227
228
229
230
231
232
233
234
235
237 bool IncludePath) const {
239 assert(BufferID && "Invalid location!");
240 auto FileSpec = getBufferInfo(BufferID).Buffer->getBufferIdentifier();
241
242 if (IncludePath) {
243 return FileSpec.str() + ":" + std::to_string(FindLineNumber(Loc, BufferID));
244 } else {
245 auto I = FileSpec.find_last_of("/\\");
246 I = (I == FileSpec.size()) ? 0 : (I + 1);
247 return FileSpec.substr(I).str() + ":" +
249 }
250}
251
252
253
255 unsigned ColNo) {
257 const char *Ptr = SB.getPointerForLineNumber(LineNo);
258 if (!Ptr)
260
261
262 if (ColNo != 0)
263 --ColNo;
264
265
266 if (ColNo) {
267
268 if (Ptr + ColNo > SB.Buffer->getBufferEnd())
270
271
274
275 Ptr += ColNo;
276 }
277
279}
280
282 if (IncludeLoc == SMLoc())
283 return;
284
286 assert(CurBuf && "Invalid or unspecified location!");
287
289
290 OS << "Included from " << getBufferInfo(CurBuf).Buffer->getBufferIdentifier()
291 << ":" << FindLineNumber(IncludeLoc, CurBuf) << ":\n";
292}
293
297
298
300 std::pair<unsigned, unsigned> LineAndCol;
301 StringRef BufferID = "";
303
304 if (Loc.isValid()) {
306 assert(CurBuf && "Invalid or unspecified location!");
307
310
311
312 const char *LineStart = Loc.getPointer();
314 while (LineStart != BufStart && LineStart[-1] != '\n' &&
315 LineStart[-1] != '\r')
316 --LineStart;
317
318
319 const char *LineEnd = Loc.getPointer();
321 while (LineEnd != BufEnd && LineEnd[0] != '\n' && LineEnd[0] != '\r')
322 ++LineEnd;
323 LineStr = StringRef(LineStart, LineEnd - LineStart);
324
325
326
327 for (SMRange R : Ranges) {
328 if (!R.isValid())
329 continue;
330
331
332 if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart)
333 continue;
334
335
336 if (R.Start.getPointer() < LineStart)
338 if (R.End.getPointer() > LineEnd)
340
341
342
343 ColRanges.push_back(std::make_pair(R.Start.getPointer() - LineStart,
344 R.End.getPointer() - LineStart));
345 }
346
348 }
349
350 return SMDiagnostic(*this, Loc, BufferID, LineAndCol.first,
351 LineAndCol.second - 1, Kind, Msg.str(), LineStr,
352 ColRanges, FixIts);
353}
354
356 bool ShowColors) const {
357
358 if (DiagHandler) {
359 DiagHandler(Diagnostic, DiagContext);
360 return;
361 }
362
365 assert(CurBuf && "Invalid or unspecified location!");
367 }
368
369 Diagnostic.print(nullptr, OS, ShowColors);
370}
371
375 bool ShowColors) const {
377}
378
384
385
386
387
388
390 : Range(R), Text(Replacement.str()) {
392}
393
394
395
396
397
401 ArrayRef<std::pair<unsigned, unsigned>> Ranges,
403 : SM(&sm), Loc(L), Filename(std::string(FN)), LineNo(Line), ColumnNo(Col),
404 Kind(Kind), Message(Msg), LineContents(LineStr), Ranges(Ranges.vec()),
405 FixIts(Hints) {
407}
408
409static void buildFixItLine(std::string &CaretLine, std::string &FixItLine,
412 if (FixIts.empty())
413 return;
414
415 const char *LineStart = SourceLine.begin();
416 const char *LineEnd = SourceLine.end();
417
418 size_t PrevHintEndCol = 0;
419
421
422 if (Fixit.getText().find_first_of("\n\r\t") != StringRef::npos)
423 continue;
424
425 SMRange R = Fixit.getRange();
426
427
428 if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart)
429 continue;
430
431
432
433
434 unsigned FirstCol;
435 if (R.Start.getPointer() < LineStart)
436 FirstCol = 0;
437 else
438 FirstCol = R.Start.getPointer() - LineStart;
439
440
441
442
443
444
445
446
447 unsigned HintCol = FirstCol;
448 if (HintCol < PrevHintEndCol)
449 HintCol = PrevHintEndCol + 1;
450
451
452
453
455 Fixit.getText().size());
456
457
458 unsigned LastColumnModified = HintCol + Fixit.getText().size();
459 if (LastColumnModified > FixItLine.size())
460 FixItLine.resize(LastColumnModified, ' ');
461
462 llvm::copy(Fixit.getText(), FixItLine.begin() + HintCol);
463
464 PrevHintEndCol = LastColumnModified;
465
466
467
468 unsigned LastCol;
469 if (R.End.getPointer() >= LineEnd)
470 LastCol = LineEnd - LineStart;
471 else
472 LastCol = R.End.getPointer() - LineStart;
473
474 std::fill(&CaretLine[FirstCol], &CaretLine[LastCol], '~');
475 }
476}
477
479
480 for (unsigned i = 0, e = LineContents.size(), OutCol = 0; i != e; ++i) {
481 size_t NextTab = LineContents.find('\t', i);
482
485 break;
486 }
487
488
489 S << LineContents.slice(i, NextTab);
490 OutCol += NextTab - i;
491 i = NextTab;
492
493
494 do {
495 S << ' ';
496 ++OutCol;
497 } while ((OutCol % TabStop) != 0);
498 }
499 S << '\n';
500}
501
502static bool isNonASCII(char c) { return c & 0x80; }
503
505 bool ShowKindLabel, bool ShowLocation) const {
507
508 {
510
511 if (ProgName && ProgName[0])
512 S << ProgName << ": ";
513
514 if (ShowLocation && !Filename.empty()) {
515 if (Filename == "-")
516 S << "";
517 else
518 S << Filename;
519
520 if (LineNo != -1) {
521 S << ':' << LineNo;
522 if (ColumnNo != -1)
523 S << ':' << (ColumnNo + 1);
524 }
525 S << ": ";
526 }
527 }
528
529 if (ShowKindLabel) {
530 switch (Kind) {
533 break;
536 break;
539 break;
542 break;
543 }
544 }
545
547
548 if (LineNo == -1 || ColumnNo == -1)
549 return;
550
551
552
553
554
555
558 return;
559 }
560 size_t NumColumns = LineContents.size();
561
562
563 std::string CaretLine(NumColumns + 1, ' ');
564
565
566 for (const std::pair<unsigned, unsigned> &R : Ranges)
567 std::fill(&CaretLine[R.first],
568 &CaretLine[std::min((size_t)R.second, CaretLine.size())], '~');
569
570
571
572 std::string FixItInsertionLine;
573 buildFixItLine(CaretLine, FixItInsertionLine, FixIts,
574 ArrayRef(Loc.getPointer() - ColumnNo, LineContents.size()));
575
576
577 if (unsigned(ColumnNo) <= NumColumns)
578 CaretLine[ColumnNo] = '^';
579 else
580 CaretLine[NumColumns] = '^';
581
582
583
584
585 CaretLine.erase(CaretLine.find_last_not_of(' ') + 1);
586
588
589 {
592
593
594 for (unsigned i = 0, e = CaretLine.size(), OutCol = 0; i != e; ++i) {
595 if (i >= LineContents.size() || LineContents[i] != '\t') {
596 S << CaretLine[i];
597 ++OutCol;
598 continue;
599 }
600
601
602 do {
603 S << CaretLine[i];
604 ++OutCol;
605 } while ((OutCol % TabStop) != 0);
606 }
607 S << '\n';
608 }
609
610
611 if (FixItInsertionLine.empty())
612 return;
613
614 for (size_t i = 0, e = FixItInsertionLine.size(), OutCol = 0; i < e; ++i) {
615 if (i >= LineContents.size() || LineContents[i] != '\t') {
616 OS << FixItInsertionLine[i];
617 ++OutCol;
618 continue;
619 }
620
621
622 do {
623 OS << FixItInsertionLine[i];
624
625
626
627
628
629 if (FixItInsertionLine[i] != ' ')
630 ++i;
631 ++OutCol;
632 } while (((OutCol % TabStop) != 0) && i != e);
633 }
634 OS << '\n';
635}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Provides ErrorOr smart pointer.
This file defines the SmallString class.
This file defines the SmallVector class.
static const size_t TabStop
Definition SourceMgr.cpp:40
static bool isNonASCII(char c)
Definition SourceMgr.cpp:502
static void buildFixItLine(std::string &CaretLine, std::string &FixItLine, ArrayRef< SMFixIt > FixIts, ArrayRef< char > SourceLine)
Definition SourceMgr.cpp:409
static void printSourceLine(raw_ostream &S, StringRef LineContents)
Definition SourceMgr.cpp:478
static std::vector< T > & GetOrCreateOffsetCache(void *&OffsetCache, MemoryBuffer *Buffer)
Definition SourceMgr.cpp:104
Defines the virtual file system interface vfs::FileSystem.
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.
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
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...
LLVM_ABI void print(const char *ProgName, raw_ostream &S, bool ShowColors=true, bool ShowKindLabel=true, bool ShowLocation=true) const
Definition SourceMgr.cpp:504
Represents a single fixit, a replacement of one range of text with another.
LLVM_ABI SMFixIt(SMRange R, const Twine &Replacement)
Definition SourceMgr.cpp:389
Represents a location in source code.
static SMLoc getFromPointer(const char *Ptr)
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.
LLVM_ABI 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,...
Definition SourceMgr.cpp:70
SourceMgr & operator=(const SourceMgr &)=delete
LLVM_ABI 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.
Definition SourceMgr.cpp:212
LLVM_ABI void setVirtualFileSystem(IntrusiveRefCntPtr< vfs::FileSystem > FS)
Definition SourceMgr.cpp:54
const MemoryBuffer * getMemoryBuffer(unsigned i) const
LLVM_ABI 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.
Definition SourceMgr.cpp:372
LLVM_ABI void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const
Prints the names of included files and the line of the file they were included from.
Definition SourceMgr.cpp:281
LLVM_ABI SourceMgr()
Create new source manager without support for include files.
LLVM_ABI unsigned FindBufferContainingLoc(SMLoc Loc) const
Return the ID of the buffer containing the specified location.
Definition SourceMgr.cpp:93
IntrusiveRefCntPtr< vfs::FileSystem > getVirtualFileSystem() const
Definition SourceMgr.cpp:50
LLVM_ABI 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.
Definition SourceMgr.cpp:294
LLVM_ABI 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.
Definition SourceMgr.cpp:58
unsigned FindLineNumber(SMLoc Loc, unsigned BufferID=0) const
Find the line number for the specified location in the specified file.
LLVM_ABI std::string getFormattedLocationNoOffset(SMLoc Loc, bool IncludePath=false) const
Get a string with the SMLoc filename and line number formatted in the standard style.
Definition SourceMgr.cpp:236
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
LLVM_ABI SMLoc FindLocForLineAndColumn(unsigned BufferID, unsigned LineNo, unsigned ColNo)
Given a line and column number in a mapped buffer, turn it into an SMLoc.
Definition SourceMgr.cpp:254
const SrcBuffer & getBufferInfo(unsigned i) const
StringRef - Represent a constant reference to a string, i.e.
static constexpr size_t npos
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.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI 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 LLVM_ABI raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
static LLVM_ABI raw_ostream & error()
Convenience method for printing "error: " to stderr.
static LLVM_ABI raw_ostream & note()
Convenience method for printing "note: " to stderr.
static LLVM_ABI 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 GREEN
static constexpr Colors SAVEDCOLOR
Offsets
Offsets in bytes from the start of the input buffer.
LLVM_ABI int columnWidth(StringRef s)
LLVM_ABI 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)
LLVM_ABI 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...
ArrayRef(const T &OneElt) -> ArrayRef< T >
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.