LLVM  3.7.0
SourceMgr.cpp
Go to the documentation of this file.
1 //===- SourceMgr.cpp - Manager for Simple Source Buffers & Diagnostics ----===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the SourceMgr class. This class is used as a simple
11 // substrate for diagnostics, #include handling, and other low level things for
12 // simple parsers.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "llvm/Support/SourceMgr.h"
17 #include "llvm/ADT/Twine.h"
18 #include "llvm/Support/Locale.h"
20 #include "llvm/Support/Path.h"
22 using namespace llvm;
23 
24 static const size_t TabStop = 8;
25 
26 namespace {
27  struct LineNoCacheTy {
28  unsigned LastQueryBufferID;
29  const char *LastQuery;
30  unsigned LineNoOfQuery;
31  };
32 }
33 
34 static LineNoCacheTy *getCache(void *Ptr) {
35  return (LineNoCacheTy*)Ptr;
36 }
37 
38 
40  // Delete the line # cache if allocated.
41  if (LineNoCacheTy *Cache = getCache(LineNoCache))
42  delete Cache;
43 }
44 
45 unsigned SourceMgr::AddIncludeFile(const std::string &Filename,
46  SMLoc IncludeLoc,
47  std::string &IncludedFile) {
48  IncludedFile = Filename;
50  MemoryBuffer::getFile(IncludedFile);
51 
52  // If the file didn't exist directly, see if it's in an include path.
53  for (unsigned i = 0, e = IncludeDirectories.size(); i != e && !NewBufOrErr;
54  ++i) {
55  IncludedFile =
56  IncludeDirectories[i] + sys::path::get_separator().data() + Filename;
57  NewBufOrErr = MemoryBuffer::getFile(IncludedFile);
58  }
59 
60  if (!NewBufOrErr)
61  return 0;
62 
63  return AddNewSourceBuffer(std::move(*NewBufOrErr), IncludeLoc);
64 }
65 
67  for (unsigned i = 0, e = Buffers.size(); i != e; ++i)
68  if (Loc.getPointer() >= Buffers[i].Buffer->getBufferStart() &&
69  // Use <= here so that a pointer to the null at the end of the buffer
70  // is included as part of the buffer.
71  Loc.getPointer() <= Buffers[i].Buffer->getBufferEnd())
72  return i + 1;
73  return 0;
74 }
75 
76 std::pair<unsigned, unsigned>
77 SourceMgr::getLineAndColumn(SMLoc Loc, unsigned BufferID) const {
78  if (!BufferID)
79  BufferID = FindBufferContainingLoc(Loc);
80  assert(BufferID && "Invalid Location!");
81 
82  const MemoryBuffer *Buff = getMemoryBuffer(BufferID);
83 
84  // Count the number of \n's between the start of the file and the specified
85  // location.
86  unsigned LineNo = 1;
87 
88  const char *BufStart = Buff->getBufferStart();
89  const char *Ptr = BufStart;
90 
91  // If we have a line number cache, and if the query is to a later point in the
92  // same file, start searching from the last query location. This optimizes
93  // for the case when multiple diagnostics come out of one file in order.
94  if (LineNoCacheTy *Cache = getCache(LineNoCache))
95  if (Cache->LastQueryBufferID == BufferID &&
96  Cache->LastQuery <= Loc.getPointer()) {
97  Ptr = Cache->LastQuery;
98  LineNo = Cache->LineNoOfQuery;
99  }
100 
101  // Scan for the location being queried, keeping track of the number of lines
102  // we see.
103  for (; SMLoc::getFromPointer(Ptr) != Loc; ++Ptr)
104  if (*Ptr == '\n') ++LineNo;
105 
106  // Allocate the line number cache if it doesn't exist.
107  if (!LineNoCache)
108  LineNoCache = new LineNoCacheTy();
109 
110  // Update the line # cache.
111  LineNoCacheTy &Cache = *getCache(LineNoCache);
112  Cache.LastQueryBufferID = BufferID;
113  Cache.LastQuery = Ptr;
114  Cache.LineNoOfQuery = LineNo;
115 
116  size_t NewlineOffs = StringRef(BufStart, Ptr-BufStart).find_last_of("\n\r");
117  if (NewlineOffs == StringRef::npos) NewlineOffs = ~(size_t)0;
118  return std::make_pair(LineNo, Ptr-BufStart-NewlineOffs);
119 }
120 
121 void SourceMgr::PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const {
122  if (IncludeLoc == SMLoc()) return; // Top of stack.
123 
124  unsigned CurBuf = FindBufferContainingLoc(IncludeLoc);
125  assert(CurBuf && "Invalid or unspecified location!");
126 
127  PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc, OS);
128 
129  OS << "Included from "
130  << getBufferInfo(CurBuf).Buffer->getBufferIdentifier()
131  << ":" << FindLineNumber(IncludeLoc, CurBuf) << ":\n";
132 }
133 
134 
136  const Twine &Msg,
138  ArrayRef<SMFixIt> FixIts) const {
139 
140  // First thing to do: find the current buffer containing the specified
141  // location to pull out the source line.
143  std::pair<unsigned, unsigned> LineAndCol;
144  const char *BufferID = "<unknown>";
145  std::string LineStr;
146 
147  if (Loc.isValid()) {
148  unsigned CurBuf = FindBufferContainingLoc(Loc);
149  assert(CurBuf && "Invalid or unspecified location!");
150 
151  const MemoryBuffer *CurMB = getMemoryBuffer(CurBuf);
152  BufferID = CurMB->getBufferIdentifier();
153 
154  // Scan backward to find the start of the line.
155  const char *LineStart = Loc.getPointer();
156  const char *BufStart = CurMB->getBufferStart();
157  while (LineStart != BufStart && LineStart[-1] != '\n' &&
158  LineStart[-1] != '\r')
159  --LineStart;
160 
161  // Get the end of the line.
162  const char *LineEnd = Loc.getPointer();
163  const char *BufEnd = CurMB->getBufferEnd();
164  while (LineEnd != BufEnd && LineEnd[0] != '\n' && LineEnd[0] != '\r')
165  ++LineEnd;
166  LineStr = std::string(LineStart, LineEnd);
167 
168  // Convert any ranges to column ranges that only intersect the line of the
169  // location.
170  for (unsigned i = 0, e = Ranges.size(); i != e; ++i) {
171  SMRange R = Ranges[i];
172  if (!R.isValid()) continue;
173 
174  // If the line doesn't contain any part of the range, then ignore it.
175  if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart)
176  continue;
177 
178  // Ignore pieces of the range that go onto other lines.
179  if (R.Start.getPointer() < LineStart)
180  R.Start = SMLoc::getFromPointer(LineStart);
181  if (R.End.getPointer() > LineEnd)
182  R.End = SMLoc::getFromPointer(LineEnd);
183 
184  // Translate from SMLoc ranges to column ranges.
185  // FIXME: Handle multibyte characters.
186  ColRanges.push_back(std::make_pair(R.Start.getPointer()-LineStart,
187  R.End.getPointer()-LineStart));
188  }
189 
190  LineAndCol = getLineAndColumn(Loc, CurBuf);
191  }
192 
193  return SMDiagnostic(*this, Loc, BufferID, LineAndCol.first,
194  LineAndCol.second-1, Kind, Msg.str(),
195  LineStr, ColRanges, FixIts);
196 }
197 
199  bool ShowColors) const {
200  // Report the message with the diagnostic handler if present.
201  if (DiagHandler) {
202  DiagHandler(Diagnostic, DiagContext);
203  return;
204  }
205 
206  if (Diagnostic.getLoc().isValid()) {
207  unsigned CurBuf = FindBufferContainingLoc(Diagnostic.getLoc());
208  assert(CurBuf && "Invalid or unspecified location!");
209  PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc, OS);
210  }
211 
212  Diagnostic.print(nullptr, OS, ShowColors);
213 }
214 
217  const Twine &Msg, ArrayRef<SMRange> Ranges,
218  ArrayRef<SMFixIt> FixIts, bool ShowColors) const {
219  PrintMessage(OS, GetMessage(Loc, Kind, Msg, Ranges, FixIts), ShowColors);
220 }
221 
223  const Twine &Msg, ArrayRef<SMRange> Ranges,
224  ArrayRef<SMFixIt> FixIts, bool ShowColors) const {
225  PrintMessage(llvm::errs(), Loc, Kind, Msg, Ranges, FixIts, ShowColors);
226 }
227 
228 //===----------------------------------------------------------------------===//
229 // SMDiagnostic Implementation
230 //===----------------------------------------------------------------------===//
231 
233  int Line, int Col, SourceMgr::DiagKind Kind,
234  StringRef Msg, StringRef LineStr,
235  ArrayRef<std::pair<unsigned,unsigned> > Ranges,
236  ArrayRef<SMFixIt> Hints)
237  : SM(&sm), Loc(L), Filename(FN), LineNo(Line), ColumnNo(Col), Kind(Kind),
238  Message(Msg), LineContents(LineStr), Ranges(Ranges.vec()),
239  FixIts(Hints.begin(), Hints.end()) {
240  std::sort(FixIts.begin(), FixIts.end());
241 }
242 
243 static void buildFixItLine(std::string &CaretLine, std::string &FixItLine,
244  ArrayRef<SMFixIt> FixIts, ArrayRef<char> SourceLine){
245  if (FixIts.empty())
246  return;
247 
248  const char *LineStart = SourceLine.begin();
249  const char *LineEnd = SourceLine.end();
250 
251  size_t PrevHintEndCol = 0;
252 
253  for (ArrayRef<SMFixIt>::iterator I = FixIts.begin(), E = FixIts.end();
254  I != E; ++I) {
255  // If the fixit contains a newline or tab, ignore it.
256  if (I->getText().find_first_of("\n\r\t") != StringRef::npos)
257  continue;
258 
259  SMRange R = I->getRange();
260 
261  // If the line doesn't contain any part of the range, then ignore it.
262  if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart)
263  continue;
264 
265  // Translate from SMLoc to column.
266  // Ignore pieces of the range that go onto other lines.
267  // FIXME: Handle multibyte characters in the source line.
268  unsigned FirstCol;
269  if (R.Start.getPointer() < LineStart)
270  FirstCol = 0;
271  else
272  FirstCol = R.Start.getPointer() - LineStart;
273 
274  // If we inserted a long previous hint, push this one forwards, and add
275  // an extra space to show that this is not part of the previous
276  // completion. This is sort of the best we can do when two hints appear
277  // to overlap.
278  //
279  // Note that if this hint is located immediately after the previous
280  // hint, no space will be added, since the location is more important.
281  unsigned HintCol = FirstCol;
282  if (HintCol < PrevHintEndCol)
283  HintCol = PrevHintEndCol + 1;
284 
285  // FIXME: This assertion is intended to catch unintended use of multibyte
286  // characters in fixits. If we decide to do this, we'll have to track
287  // separate byte widths for the source and fixit lines.
288  assert((size_t)llvm::sys::locale::columnWidth(I->getText()) ==
289  I->getText().size());
290 
291  // This relies on one byte per column in our fixit hints.
292  unsigned LastColumnModified = HintCol + I->getText().size();
293  if (LastColumnModified > FixItLine.size())
294  FixItLine.resize(LastColumnModified, ' ');
295 
296  std::copy(I->getText().begin(), I->getText().end(),
297  FixItLine.begin() + HintCol);
298 
299  PrevHintEndCol = LastColumnModified;
300 
301  // For replacements, mark the removal range with '~'.
302  // FIXME: Handle multibyte characters in the source line.
303  unsigned LastCol;
304  if (R.End.getPointer() >= LineEnd)
305  LastCol = LineEnd - LineStart;
306  else
307  LastCol = R.End.getPointer() - LineStart;
308 
309  std::fill(&CaretLine[FirstCol], &CaretLine[LastCol], '~');
310  }
311 }
312 
313 static void printSourceLine(raw_ostream &S, StringRef LineContents) {
314  // Print out the source line one character at a time, so we can expand tabs.
315  for (unsigned i = 0, e = LineContents.size(), OutCol = 0; i != e; ++i) {
316  if (LineContents[i] != '\t') {
317  S << LineContents[i];
318  ++OutCol;
319  continue;
320  }
321 
322  // If we have a tab, emit at least one space, then round up to 8 columns.
323  do {
324  S << ' ';
325  ++OutCol;
326  } while ((OutCol % TabStop) != 0);
327  }
328  S << '\n';
329 }
330 
331 static bool isNonASCII(char c) {
332  return c & 0x80;
333 }
334 
335 void SMDiagnostic::print(const char *ProgName, raw_ostream &S, bool ShowColors,
336  bool ShowKindLabel) const {
337  // Display colors only if OS supports colors.
338  ShowColors &= S.has_colors();
339 
340  if (ShowColors)
342 
343  if (ProgName && ProgName[0])
344  S << ProgName << ": ";
345 
346  if (!Filename.empty()) {
347  if (Filename == "-")
348  S << "<stdin>";
349  else
350  S << Filename;
351 
352  if (LineNo != -1) {
353  S << ':' << LineNo;
354  if (ColumnNo != -1)
355  S << ':' << (ColumnNo+1);
356  }
357  S << ": ";
358  }
359 
360  if (ShowKindLabel) {
361  switch (Kind) {
362  case SourceMgr::DK_Error:
363  if (ShowColors)
364  S.changeColor(raw_ostream::RED, true);
365  S << "error: ";
366  break;
368  if (ShowColors)
370  S << "warning: ";
371  break;
372  case SourceMgr::DK_Note:
373  if (ShowColors)
375  S << "note: ";
376  break;
377  }
378 
379  if (ShowColors) {
380  S.resetColor();
382  }
383  }
384 
385  S << Message << '\n';
386 
387  if (ShowColors)
388  S.resetColor();
389 
390  if (LineNo == -1 || ColumnNo == -1)
391  return;
392 
393  // FIXME: If there are multibyte or multi-column characters in the source, all
394  // our ranges will be wrong. To do this properly, we'll need a byte-to-column
395  // map like Clang's TextDiagnostic. For now, we'll just handle tabs by
396  // expanding them later, and bail out rather than show incorrect ranges and
397  // misaligned fixits for any other odd characters.
398  if (std::find_if(LineContents.begin(), LineContents.end(), isNonASCII) !=
399  LineContents.end()) {
400  printSourceLine(S, LineContents);
401  return;
402  }
403  size_t NumColumns = LineContents.size();
404 
405  // Build the line with the caret and ranges.
406  std::string CaretLine(NumColumns+1, ' ');
407 
408  // Expand any ranges.
409  for (unsigned r = 0, e = Ranges.size(); r != e; ++r) {
410  std::pair<unsigned, unsigned> R = Ranges[r];
411  std::fill(&CaretLine[R.first],
412  &CaretLine[std::min((size_t)R.second, CaretLine.size())],
413  '~');
414  }
415 
416  // Add any fix-its.
417  // FIXME: Find the beginning of the line properly for multibyte characters.
418  std::string FixItInsertionLine;
419  buildFixItLine(CaretLine, FixItInsertionLine, FixIts,
420  makeArrayRef(Loc.getPointer() - ColumnNo,
421  LineContents.size()));
422 
423  // Finally, plop on the caret.
424  if (unsigned(ColumnNo) <= NumColumns)
425  CaretLine[ColumnNo] = '^';
426  else
427  CaretLine[NumColumns] = '^';
428 
429  // ... and remove trailing whitespace so the output doesn't wrap for it. We
430  // know that the line isn't completely empty because it has the caret in it at
431  // least.
432  CaretLine.erase(CaretLine.find_last_not_of(' ')+1);
433 
434  printSourceLine(S, LineContents);
435 
436  if (ShowColors)
438 
439  // Print out the caret line, matching tabs in the source line.
440  for (unsigned i = 0, e = CaretLine.size(), OutCol = 0; i != e; ++i) {
441  if (i >= LineContents.size() || LineContents[i] != '\t') {
442  S << CaretLine[i];
443  ++OutCol;
444  continue;
445  }
446 
447  // Okay, we have a tab. Insert the appropriate number of characters.
448  do {
449  S << CaretLine[i];
450  ++OutCol;
451  } while ((OutCol % TabStop) != 0);
452  }
453  S << '\n';
454 
455  if (ShowColors)
456  S.resetColor();
457 
458  // Print out the replacement line, matching tabs in the source line.
459  if (FixItInsertionLine.empty())
460  return;
461 
462  for (size_t i = 0, e = FixItInsertionLine.size(), OutCol = 0; i < e; ++i) {
463  if (i >= LineContents.size() || LineContents[i] != '\t') {
464  S << FixItInsertionLine[i];
465  ++OutCol;
466  continue;
467  }
468 
469  // Okay, we have a tab. Insert the appropriate number of characters.
470  do {
471  S << FixItInsertionLine[i];
472  // FIXME: This is trying not to break up replacements, but then to re-sync
473  // with the tabs between replacements. This will fail, though, if two
474  // fix-it replacements are exactly adjacent, or if a fix-it contains a
475  // space. Really we should be precomputing column widths, which we'll
476  // need anyway for multibyte chars.
477  if (FixItInsertionLine[i] != ' ')
478  ++i;
479  ++OutCol;
480  } while (((OutCol % TabStop) != 0) && i != e);
481  }
482  S << '\n';
483 }
void print(const char *ProgName, raw_ostream &S, bool ShowColors=true, bool ShowKindLabel=true) const
Definition: SourceMgr.cpp:335
Represents a range in source code.
Definition: SMLoc.h:47
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:240
Represents either an error or a value T.
Definition: ErrorOr.h:82
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
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:121
const char * getPointer() const
Definition: SMLoc.h:33
size_t size() const
size - Get the string size.
Definition: StringRef.h:113
const char * getBufferStart() const
Definition: MemoryBuffer.h:50
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:77
iterator end() const
Definition: ArrayRef.h:123
virtual bool has_colors() const
This function determines if this stream is displayed and supports colors.
Definition: raw_ostream.h:258
static const char * ProgName
virtual raw_ostream & changeColor(enum Colors Color, bool Bold=false, bool BG=false)
Changes the foreground color of text that will be output from this point forward. ...
Definition: raw_ostream.h:236
const_iterator begin(StringRef path)
Get begin iterator over path.
Definition: Path.cpp:232
SMLoc Start
Definition: SMLoc.h:49
virtual const char * getBufferIdentifier() const
Return an identifier for this buffer, typically the filename it was read from.
Definition: MemoryBuffer.h:60
std::string str() const
Return the twine contents as a std::string.
Definition: Twine.cpp:16
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:79
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Definition: ArrayRef.h:308
SMLoc getLoc() const
Definition: SourceMgr.h:260
Number of individual test Apply this number of consecutive mutations to each input exit after the first new interesting input is found the minimized corpus is saved into the first input directory Number of jobs to run If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
bool isValid() const
Definition: SMLoc.h:28
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:107
static const size_t TabStop
Definition: SourceMgr.cpp:24
unsigned AddNewSourceBuffer(std::unique_ptr< MemoryBuffer > F, SMLoc IncludeLoc)
Add a new source buffer to this source manager.
Definition: SourceMgr.h:123
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: ArrayRef.h:31
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:134
int columnWidth(StringRef s)
Definition: Locale.cpp:8
iterator begin() const
Definition: ArrayRef.h:122
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:129
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling...
Definition: SourceMgr.h:35
const SrcBuffer & getBufferInfo(unsigned i) const
Definition: SourceMgr.h:97
static LineNoCacheTy * getCache(void *Ptr)
Definition: SourceMgr.cpp:34
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.
Definition: StringRef.h:301
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:861
static void printSourceLine(raw_ostream &S, StringRef LineContents)
Definition: SourceMgr.cpp:313
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:37
unsigned FindLineNumber(SMLoc Loc, unsigned BufferID=0) const
Find the line number for the specified location in the specified file.
Definition: SourceMgr.h:148
StringRef get_separator()
Return the preferred separator for this platform.
Definition: Path.cpp:590
SMLoc End
Definition: SMLoc.h:49
static bool isNonASCII(char c)
Definition: SourceMgr.cpp:331
static SMLoc getFromPointer(const char *Ptr)
Definition: SMLoc.h:35
SI Fix SGPR Live Ranges
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:45
const MemoryBuffer * getMemoryBuffer(unsigned i) const
Definition: SourceMgr.h:102
static const size_t npos
Definition: StringRef.h:44
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatileSize=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
#define I(x, y, z)
Definition: MD5.cpp:54
bool isValid() const
Definition: SMLoc.h:57
static void buildFixItLine(std::string &CaretLine, std::string &FixItLine, ArrayRef< SMFixIt > FixIts, ArrayRef< char > SourceLine)
Definition: SourceMgr.cpp:243
const char * getBufferEnd() const
Definition: MemoryBuffer.h:51
unsigned FindBufferContainingLoc(SMLoc Loc) const
Return the ID of the buffer containing the specified location.
Definition: SourceMgr.cpp:66
const ARM::ArchExtKind Kind
virtual raw_ostream & resetColor()
Resets the colors to terminal defaults.
Definition: raw_ostream.h:247
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:38
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges=None, ArrayRef< SMFixIt > FixIts=None) const
Return an SMDiagnostic at the specified location with the specified string.
Definition: SourceMgr.cpp:135
void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges=None, ArrayRef< SMFixIt > FixIts=None, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
Definition: SourceMgr.cpp:215
Represents a location in source code.
Definition: SMLoc.h:23
Instances of this class encapsulate one diagnostic report, allowing printing to a raw_ostream as a ca...
Definition: SourceMgr.h:233