LLVM  3.7.0
GCOV.h
Go to the documentation of this file.
1 //===- GCOV.h - LLVM coverage tool ----------------------------------------===//
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 header provides the interface to read and write coverage files that
11 // use 'gcov' format.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_SUPPORT_GCOV_H
16 #define LLVM_SUPPORT_GCOV_H
17 
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/ADT/MapVector.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/StringMap.h"
22 #include "llvm/ADT/iterator.h"
25 
26 namespace llvm {
27 
28 class GCOVFunction;
29 class GCOVBlock;
30 class FileInfo;
31 
32 namespace GCOV {
33 enum GCOVVersion { V402, V404 };
34 } // end GCOV namespace
35 
36 /// GCOVOptions - A struct for passing gcov options between functions.
37 struct GCOVOptions {
38  GCOVOptions(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N)
41 
42  bool AllBlocks;
43  bool BranchInfo;
49  bool NoOutput;
50 };
51 
52 /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific
53 /// read operations.
54 class GCOVBuffer {
55 public:
56  GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {}
57 
58  /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
59  bool readGCNOFormat() {
60  StringRef File = Buffer->getBuffer().slice(0, 4);
61  if (File != "oncg") {
62  errs() << "Unexpected file type: " << File << ".\n";
63  return false;
64  }
65  Cursor = 4;
66  return true;
67  }
68 
69  /// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer.
70  bool readGCDAFormat() {
71  StringRef File = Buffer->getBuffer().slice(0, 4);
72  if (File != "adcg") {
73  errs() << "Unexpected file type: " << File << ".\n";
74  return false;
75  }
76  Cursor = 4;
77  return true;
78  }
79 
80  /// readGCOVVersion - Read GCOV version.
82  StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor + 4);
83  if (VersionStr == "*204") {
84  Cursor += 4;
85  Version = GCOV::V402;
86  return true;
87  }
88  if (VersionStr == "*404") {
89  Cursor += 4;
90  Version = GCOV::V404;
91  return true;
92  }
93  errs() << "Unexpected version: " << VersionStr << ".\n";
94  return false;
95  }
96 
97  /// readFunctionTag - If cursor points to a function tag then increment the
98  /// cursor and return true otherwise return false.
99  bool readFunctionTag() {
100  StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
101  if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
102  Tag[3] != '\1') {
103  return false;
104  }
105  Cursor += 4;
106  return true;
107  }
108 
109  /// readBlockTag - If cursor points to a block tag then increment the
110  /// cursor and return true otherwise return false.
111  bool readBlockTag() {
112  StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
113  if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x41' ||
114  Tag[3] != '\x01') {
115  return false;
116  }
117  Cursor += 4;
118  return true;
119  }
120 
121  /// readEdgeTag - If cursor points to an edge tag then increment the
122  /// cursor and return true otherwise return false.
123  bool readEdgeTag() {
124  StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
125  if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x43' ||
126  Tag[3] != '\x01') {
127  return false;
128  }
129  Cursor += 4;
130  return true;
131  }
132 
133  /// readLineTag - If cursor points to a line tag then increment the
134  /// cursor and return true otherwise return false.
135  bool readLineTag() {
136  StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
137  if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x45' ||
138  Tag[3] != '\x01') {
139  return false;
140  }
141  Cursor += 4;
142  return true;
143  }
144 
145  /// readArcTag - If cursor points to an gcda arc tag then increment the
146  /// cursor and return true otherwise return false.
147  bool readArcTag() {
148  StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
149  if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\xa1' ||
150  Tag[3] != '\1') {
151  return false;
152  }
153  Cursor += 4;
154  return true;
155  }
156 
157  /// readObjectTag - If cursor points to an object summary tag then increment
158  /// the cursor and return true otherwise return false.
159  bool readObjectTag() {
160  StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
161  if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
162  Tag[3] != '\xa1') {
163  return false;
164  }
165  Cursor += 4;
166  return true;
167  }
168 
169  /// readProgramTag - If cursor points to a program summary tag then increment
170  /// the cursor and return true otherwise return false.
171  bool readProgramTag() {
172  StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4);
173  if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' ||
174  Tag[3] != '\xa3') {
175  return false;
176  }
177  Cursor += 4;
178  return true;
179  }
180 
181  bool readInt(uint32_t &Val) {
182  if (Buffer->getBuffer().size() < Cursor + 4) {
183  errs() << "Unexpected end of memory buffer: " << Cursor + 4 << ".\n";
184  return false;
185  }
186  StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor + 4);
187  Cursor += 4;
188  Val = *(const uint32_t *)(Str.data());
189  return true;
190  }
191 
192  bool readInt64(uint64_t &Val) {
193  uint32_t Lo, Hi;
194  if (!readInt(Lo) || !readInt(Hi))
195  return false;
196  Val = ((uint64_t)Hi << 32) | Lo;
197  return true;
198  }
199 
200  bool readString(StringRef &Str) {
201  uint32_t Len = 0;
202  // Keep reading until we find a non-zero length. This emulates gcov's
203  // behaviour, which appears to do the same.
204  while (Len == 0)
205  if (!readInt(Len))
206  return false;
207  Len *= 4;
208  if (Buffer->getBuffer().size() < Cursor + Len) {
209  errs() << "Unexpected end of memory buffer: " << Cursor + Len << ".\n";
210  return false;
211  }
212  Str = Buffer->getBuffer().slice(Cursor, Cursor + Len).split('\0').first;
213  Cursor += Len;
214  return true;
215  }
216 
217  uint64_t getCursor() const { return Cursor; }
218  void advanceCursor(uint32_t n) { Cursor += n * 4; }
219 
220 private:
221  MemoryBuffer *Buffer;
222  uint64_t Cursor;
223 };
224 
225 /// GCOVFile - Collects coverage information for one pair of coverage file
226 /// (.gcno and .gcda).
227 class GCOVFile {
228 public:
230  : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0),
231  ProgramCount(0) {}
232  bool readGCNO(GCOVBuffer &Buffer);
233  bool readGCDA(GCOVBuffer &Buffer);
234  uint32_t getChecksum() const { return Checksum; }
235  void dump() const;
236  void collectLineCounts(FileInfo &FI);
237 
238 private:
239  bool GCNOInitialized;
240  GCOV::GCOVVersion Version;
241  uint32_t Checksum;
243  uint32_t RunCount;
244  uint32_t ProgramCount;
245 };
246 
247 /// GCOVEdge - Collects edge information.
248 struct GCOVEdge {
249  GCOVEdge(GCOVBlock &S, GCOVBlock &D) : Src(S), Dst(D), Count(0) {}
250 
253  uint64_t Count;
254 };
255 
256 /// GCOVFunction - Collects function information.
258 public:
260  std::unique_ptr<GCOVBlock>>::const_iterator> BlockIterator;
261 
262  GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {}
265  StringRef getName() const { return Name; }
266  StringRef getFilename() const { return Filename; }
267  size_t getNumBlocks() const { return Blocks.size(); }
268  uint64_t getEntryCount() const;
269  uint64_t getExitCount() const;
270 
271  BlockIterator block_begin() const { return Blocks.begin(); }
272  BlockIterator block_end() const { return Blocks.end(); }
274  return make_range(block_begin(), block_end());
275  }
276 
277  void dump() const;
278  void collectLineCounts(FileInfo &FI);
279 
280 private:
281  GCOVFile &Parent;
282  uint32_t Ident;
283  uint32_t Checksum;
284  uint32_t LineNumber;
285  StringRef Name;
286  StringRef Filename;
289 };
290 
291 /// GCOVBlock - Collects block information.
292 class GCOVBlock {
293  struct EdgeWeight {
294  EdgeWeight(GCOVBlock *D) : Dst(D), Count(0) {}
295 
296  GCOVBlock *Dst;
297  uint64_t Count;
298  };
299 
300  struct SortDstEdgesFunctor {
301  bool operator()(const GCOVEdge *E1, const GCOVEdge *E2) {
302  return E1->Dst.Number < E2->Dst.Number;
303  }
304  };
305 
306 public:
308 
309  GCOVBlock(GCOVFunction &P, uint32_t N)
310  : Parent(P), Number(N), Counter(0), DstEdgesAreSorted(true), SrcEdges(),
311  DstEdges(), Lines() {}
312  ~GCOVBlock();
313  const GCOVFunction &getParent() const { return Parent; }
314  void addLine(uint32_t N) { Lines.push_back(N); }
315  uint32_t getLastLine() const { return Lines.back(); }
316  void addCount(size_t DstEdgeNo, uint64_t N);
317  uint64_t getCount() const { return Counter; }
318 
319  void addSrcEdge(GCOVEdge *Edge) {
320  assert(&Edge->Dst == this); // up to caller to ensure edge is valid
321  SrcEdges.push_back(Edge);
322  }
323  void addDstEdge(GCOVEdge *Edge) {
324  assert(&Edge->Src == this); // up to caller to ensure edge is valid
325  // Check if adding this edge causes list to become unsorted.
326  if (DstEdges.size() && DstEdges.back()->Dst.Number > Edge->Dst.Number)
327  DstEdgesAreSorted = false;
328  DstEdges.push_back(Edge);
329  }
330  size_t getNumSrcEdges() const { return SrcEdges.size(); }
331  size_t getNumDstEdges() const { return DstEdges.size(); }
332  void sortDstEdges();
333 
334  EdgeIterator src_begin() const { return SrcEdges.begin(); }
335  EdgeIterator src_end() const { return SrcEdges.end(); }
337  return make_range(src_begin(), src_end());
338  }
339 
340  EdgeIterator dst_begin() const { return DstEdges.begin(); }
341  EdgeIterator dst_end() const { return DstEdges.end(); }
343  return make_range(dst_begin(), dst_end());
344  }
345 
346  void dump() const;
347  void collectLineCounts(FileInfo &FI);
348 
349 private:
350  GCOVFunction &Parent;
351  uint32_t Number;
352  uint64_t Counter;
353  bool DstEdgesAreSorted;
357 };
358 
359 class FileInfo {
360  // It is unlikely--but possible--for multiple functions to be on the same
361  // line.
362  // Therefore this typedef allows LineData.Functions to store multiple
363  // functions
364  // per instance. This is rare, however, so optimize for the common case.
369 
370  struct LineData {
371  LineData() : LastLine(0) {}
372  BlockLines Blocks;
373  FunctionLines Functions;
374  uint32_t LastLine;
375  };
376 
377  struct GCOVCoverage {
378  GCOVCoverage(StringRef Name)
379  : Name(Name), LogicalLines(0), LinesExec(0), Branches(0),
380  BranchesExec(0), BranchesTaken(0) {}
381 
382  StringRef Name;
383 
384  uint32_t LogicalLines;
385  uint32_t LinesExec;
386 
387  uint32_t Branches;
388  uint32_t BranchesExec;
389  uint32_t BranchesTaken;
390  };
391 
392 public:
393  FileInfo(const GCOVOptions &Options)
394  : Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {}
395 
396  void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) {
397  if (Line > LineInfo[Filename].LastLine)
398  LineInfo[Filename].LastLine = Line;
399  LineInfo[Filename].Blocks[Line - 1].push_back(Block);
400  }
401  void addFunctionLine(StringRef Filename, uint32_t Line,
402  const GCOVFunction *Function) {
403  if (Line > LineInfo[Filename].LastLine)
404  LineInfo[Filename].LastLine = Line;
405  LineInfo[Filename].Functions[Line - 1].push_back(Function);
406  }
407  void setRunCount(uint32_t Runs) { RunCount = Runs; }
408  void setProgramCount(uint32_t Programs) { ProgramCount = Programs; }
409  void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile,
410  StringRef GCDAFile);
411 
412 private:
413  std::string getCoveragePath(StringRef Filename, StringRef MainFilename);
414  std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath);
415  void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const;
416  void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block,
417  uint32_t LineIndex, uint32_t &BlockNo) const;
418  void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block,
419  GCOVCoverage &Coverage, uint32_t &EdgeNo);
420  void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo,
421  uint64_t Count) const;
422 
423  void printCoverage(raw_ostream &OS, const GCOVCoverage &Coverage) const;
424  void printFuncCoverage(raw_ostream &OS) const;
425  void printFileCoverage(raw_ostream &OS) const;
426 
427  const GCOVOptions &Options;
428  StringMap<LineData> LineInfo;
429  uint32_t RunCount;
430  uint32_t ProgramCount;
431 
432  typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4> FileCoverageList;
433  typedef MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverageMap;
434 
435  FileCoverageList FileCoverages;
436  FuncCoverageMap FuncCoverages;
437 };
438 }
439 
440 #endif
GCOVOptions - A struct for passing gcov options between functions.
Definition: GCOV.h:37
void push_back(const T &Elt)
Definition: SmallVector.h:222
iterator_range< EdgeIterator > dsts() const
Definition: GCOV.h:342
GCOVBlock(GCOVFunction &P, uint32_t N)
Definition: GCOV.h:309
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version)
readGCNO - Read a function from the GCNO buffer.
Definition: GCOV.cpp:126
EdgeIterator dst_begin() const
Definition: GCOV.h:340
bool readInt(uint32_t &Val)
Definition: GCOV.h:181
bool readGCDAFormat()
readGCDAFormat - Check GCDA signature is valid at the beginning of buffer.
Definition: GCOV.h:70
size_t size() const
size - Get the string size.
Definition: StringRef.h:113
GCOVEdge - Collects edge information.
Definition: GCOV.h:248
GCOVBlock & Src
Definition: GCOV.h:251
void addFunctionLine(StringRef Filename, uint32_t Line, const GCOVFunction *Function)
Definition: GCOV.h:401
void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile, StringRef GCDAFile)
print - Print source files with collected line count information.
Definition: GCOV.cpp:568
uint64_t getCount() const
Definition: GCOV.h:317
bool readLineTag()
readLineTag - If cursor points to a line tag then increment the cursor and return true otherwise retu...
Definition: GCOV.h:135
void setProgramCount(uint32_t Programs)
Definition: GCOV.h:408
bool BranchInfo
Definition: GCOV.h:43
SmallVectorImpl< GCOVEdge * >::const_iterator EdgeIterator
Definition: GCOV.h:307
BlockIterator block_begin() const
Definition: GCOV.h:271
bool readString(StringRef &Str)
Definition: GCOV.h:200
size_t getNumBlocks() const
Definition: GCOV.h:267
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:450
uint32_t getChecksum() const
Definition: GCOV.h:234
void addLine(uint32_t N)
Definition: GCOV.h:314
StringRef getBuffer() const
Definition: MemoryBuffer.h:54
F(f)
void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block)
Definition: GCOV.h:396
GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific read operations.
Definition: GCOV.h:54
uint32_t getLastLine() const
Definition: GCOV.h:315
iterator_range< BlockIterator > blocks() const
Definition: GCOV.h:273
StringRef getName() const
Definition: GCOV.h:265
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APInt.h:33
EdgeIterator dst_end() const
Definition: GCOV.h:341
void collectLineCounts(FileInfo &FI)
collectLineCounts - Collect line counts.
Definition: GCOV.cpp:352
#define false
Definition: ConvertUTF.c:65
bool NoOutput
Definition: GCOV.h:49
GCOVBlock & Dst
Definition: GCOV.h:252
bool readGCDA(GCOVBuffer &Buffer)
readGCDA - Read GCDA buffer.
Definition: GCOV.cpp:54
bool readArcTag()
readArcTag - If cursor points to an gcda arc tag then increment the cursor and return true otherwise ...
Definition: GCOV.h:147
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:107
void addDstEdge(GCOVEdge *Edge)
Definition: GCOV.h:323
GCOVBlock - Collects block information.
Definition: GCOV.h:292
uint64_t getExitCount() const
getExitCount - Get the number of times the function returned by retrieving the exit block's count...
Definition: GCOV.cpp:338
GCOVFunction(GCOVFile &P)
Definition: GCOV.h:262
iterator_range< EdgeIterator > srcs() const
Definition: GCOV.h:336
pointee_iterator< SmallVectorImpl< std::unique_ptr< GCOVBlock > >::const_iterator > BlockIterator
Definition: GCOV.h:260
void sortDstEdges()
sortDstEdges - Sort destination edges by block number, nop if already sorted.
Definition: GCOV.cpp:385
bool readInt64(uint64_t &Val)
Definition: GCOV.h:192
void collectLineCounts(FileInfo &FI)
collectLineCounts - Collect line counts.
Definition: GCOV.cpp:114
EdgeIterator src_begin() const
Definition: GCOV.h:334
#define P(N)
#define true
Definition: ConvertUTF.c:66
void addSrcEdge(GCOVEdge *Edge)
Definition: GCOV.h:319
bool BranchCount
Definition: GCOV.h:44
void dump() const
dump - Dump GCOVFile content to dbgs() for debugging purposes.
Definition: GCOV.cpp:107
bool readBlockTag()
readBlockTag - If cursor points to a block tag then increment the cursor and return true otherwise re...
Definition: GCOV.h:111
BlockIterator block_end() const
Definition: GCOV.h:272
bool readGCNOFormat()
readGCNOFormat - Check GCNO signature is valid at the beginning of buffer.
Definition: GCOV.h:59
void advanceCursor(uint32_t n)
Definition: GCOV.h:218
bool readGCNO(GCOVBuffer &Buffer)
readGCNO - Read GCNO buffer.
Definition: GCOV.cpp:31
GCOVVersion
Definition: GCOV.h:33
const GCOVFunction & getParent() const
Definition: GCOV.h:313
bool FuncCoverage
Definition: GCOV.h:45
bool readEdgeTag()
readEdgeTag - If cursor points to an edge tag then increment the cursor and return true otherwise ret...
Definition: GCOV.h:123
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
GCOVBuffer(MemoryBuffer *B)
Definition: GCOV.h:56
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:861
bool AllBlocks
Definition: GCOV.h:42
GCOVEdge(GCOVBlock &S, GCOVBlock &D)
Definition: GCOV.h:249
An iterator type that allows iterating over the pointees via some other iterator. ...
Definition: iterator.h:231
bool UncondBranch
Definition: GCOV.h:47
void dump() const
dump - Dump GCOVFunction content to dbgs() for debugging purposes.
Definition: GCOV.cpp:343
bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version)
readGCDA - Read a function from the GCDA buffer.
Definition: GCOV.cpp:249
This interface provides simple read-only access to a block of memory, and provides simple methods for...
Definition: MemoryBuffer.h:37
EdgeIterator src_end() const
Definition: GCOV.h:335
A range adaptor for a pair of iterators.
bool PreservePaths
Definition: GCOV.h:46
size_t getNumSrcEdges() const
Definition: GCOV.h:330
StringRef getFilename() const
Definition: GCOV.h:266
GCOVOptions(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N)
Definition: GCOV.h:38
void collectLineCounts(FileInfo &FI)
collectLineCounts - Collect line counts.
Definition: GCOV.cpp:394
bool LongFileNames
Definition: GCOV.h:48
GCOVFunction - Collects function information.
Definition: GCOV.h:257
size_t getNumDstEdges() const
Definition: GCOV.h:331
void dump() const
dump - Dump GCOVBlock content to dbgs() for debugging purposes.
Definition: GCOV.cpp:400
#define N
bool readObjectTag()
readObjectTag - If cursor points to an object summary tag then increment the cursor and return true o...
Definition: GCOV.h:159
GCOVFile - Collects coverage information for one pair of coverage file (.gcno and ...
Definition: GCOV.h:227
uint64_t Count
Definition: GCOV.h:253
uint64_t getEntryCount() const
getEntryCount - Get the number of times the function was called by retrieving the entry block's count...
Definition: GCOV.cpp:332
uint64_t getCursor() const
Definition: GCOV.h:217
~GCOVBlock()
~GCOVBlock - Delete GCOVBlock and its content.
Definition: GCOV.cpp:367
FileInfo(const GCOVOptions &Options)
Definition: GCOV.h:393
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:38
bool readProgramTag()
readProgramTag - If cursor points to a program summary tag then increment the cursor and return true ...
Definition: GCOV.h:171
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
bool readFunctionTag()
readFunctionTag - If cursor points to a function tag then increment the cursor and return true otherw...
Definition: GCOV.h:99
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition: StringRef.h:434
void addCount(size_t DstEdgeNo, uint64_t N)
addCount - Add to block counter while storing the edge count.
Definition: GCOV.cpp:375
void setRunCount(uint32_t Runs)
Definition: GCOV.h:407
bool readGCOVVersion(GCOV::GCOVVersion &Version)
readGCOVVersion - Read GCOV version.
Definition: GCOV.h:81
bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:110