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