1 //===--- TextDiagnostic.cpp - Text Diagnostic Pretty-Printing -------------===//
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 #include "clang/Frontend/TextDiagnostic.h"
11 #include "clang/Basic/FileManager.h"
12 #include "clang/Basic/SourceManager.h"
13 #include "clang/Basic/ConvertUTF.h"
14 #include "clang/Frontend/DiagnosticOptions.h"
15 #include "clang/Lex/Lexer.h"
16 #include "llvm/Support/MemoryBuffer.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/Support/Locale.h"
20 #include "llvm/ADT/SmallString.h"
21 #include "llvm/ADT/StringExtras.h"
22 #include <algorithm>
23 #include <cctype>
24 
25 using namespace clang;
26 
27 static const enum raw_ostream::Colors noteColor =
28   raw_ostream::BLACK;
29 static const enum raw_ostream::Colors fixitColor =
30   raw_ostream::GREEN;
31 static const enum raw_ostream::Colors caretColor =
32   raw_ostream::GREEN;
33 static const enum raw_ostream::Colors warningColor =
34   raw_ostream::MAGENTA;
35 static const enum raw_ostream::Colors templateColor =
36   raw_ostream::CYAN;
37 static const enum raw_ostream::Colors errorColor = raw_ostream::RED;
38 static const enum raw_ostream::Colors fatalColor = raw_ostream::RED;
39 // Used for changing only the bold attribute.
40 static const enum raw_ostream::Colors savedColor =
41   raw_ostream::SAVEDCOLOR;
42 
43 /// \brief Add highlights to differences in template strings.
44 static void applyTemplateHighlighting(raw_ostream &OS, StringRef Str,
45                                       bool &Normal, bool Bold) {
46   for (unsigned i = 0, e = Str.size(); i < e; ++i)
47     if (Str[i] != ToggleHighlight) {
48       OS << Str[i];
49     } else {
50       if (Normal)
51         OS.changeColor(templateColor, true);
52       else {
53         OS.resetColor();
54         if (Bold)
55           OS.changeColor(savedColor, true);
56       }
57       Normal = !Normal;
58     }
59 }
60 
61 /// \brief Number of spaces to indent when word-wrapping.
62 const unsigned WordWrapIndentation = 6;
63 
64 static int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i) {
65   int bytes = 0;
66   while (0<i) {
67     if (SourceLine[--i]=='\t')
68       break;
69     ++bytes;
70   }
71   return bytes;
72 }
73 
74 /// \brief returns a printable representation of first item from input range
75 ///
76 /// This function returns a printable representation of the next item in a line
77 ///  of source. If the next byte begins a valid and printable character, that
78 ///  character is returned along with 'true'.
79 ///
80 /// Otherwise, if the next byte begins a valid, but unprintable character, a
81 ///  printable, escaped representation of the character is returned, along with
82 ///  'false'. Otherwise a printable, escaped representation of the next byte
83 ///  is returned along with 'false'.
84 ///
85 /// \note The index is updated to be used with a subsequent call to
86 ///        printableTextForNextCharacter.
87 ///
88 /// \param SourceLine The line of source
89 /// \param i Pointer to byte index,
90 /// \param TabStop used to expand tabs
91 /// \return pair(printable text, 'true' iff original text was printable)
92 ///
93 static std::pair<SmallString<16>, bool>
94 printableTextForNextCharacter(StringRef SourceLine, size_t *i,
95                               unsigned TabStop) {
96   assert(i && "i must not be null");
97   assert(*i<SourceLine.size() && "must point to a valid index");
98 
99   if (SourceLine[*i]=='\t') {
100     assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop &&
101            "Invalid -ftabstop value");
102     unsigned col = bytesSincePreviousTabOrLineBegin(SourceLine, *i);
103     unsigned NumSpaces = TabStop - col%TabStop;
104     assert(0 < NumSpaces && NumSpaces <= TabStop
105            && "Invalid computation of space amt");
106     ++(*i);
107 
108     SmallString<16> expandedTab;
109     expandedTab.assign(NumSpaces, ' ');
110     return std::make_pair(expandedTab, true);
111   }
112 
113   // FIXME: this data is copied from the private implementation of ConvertUTF.h
114   static const char trailingBytesForUTF8[256] = {
115     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
116     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
117     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
118     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
119     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
120     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
121     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
122     2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
123   };
124 
125   unsigned char const *begin, *end;
126   begin = reinterpret_cast<unsigned char const *>(&*(SourceLine.begin() + *i));
127   end = begin + SourceLine.size();
128 
129   if (isLegalUTF8Sequence(begin, end)) {
130     UTF32 c;
131     UTF32 *cptr = &c;
132     unsigned char const *original_begin = begin;
133     char trailingBytes = trailingBytesForUTF8[(unsigned char)SourceLine[*i]];
134     unsigned char const *cp_end = begin+trailingBytes+1;
135 
136     ConversionResult res = ConvertUTF8toUTF32(&begin, cp_end, &cptr, cptr+1,
137                                               strictConversion);
138     (void)res;
139     assert(conversionOK==res);
140     assert(0 < begin-original_begin
141            && "we must be further along in the string now");
142     *i += begin-original_begin;
143 
144     if (!llvm::sys::locale::isPrint(c)) {
145       // If next character is valid UTF-8, but not printable
146       SmallString<16> expandedCP("<U+>");
147       while (c) {
148         expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(c%16));
149         c/=16;
150       }
151       while (expandedCP.size() < 8)
152         expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(0));
153       return std::make_pair(expandedCP, false);
154     }
155 
156     // If next character is valid UTF-8, and printable
157     return std::make_pair(SmallString<16>(original_begin, cp_end), true);
158 
159   }
160 
161   // If next byte is not valid UTF-8 (and therefore not printable)
162   SmallString<16> expandedByte("<XX>");
163   unsigned char byte = SourceLine[*i];
164   expandedByte[1] = llvm::hexdigit(byte / 16);
165   expandedByte[2] = llvm::hexdigit(byte % 16);
166   ++(*i);
167   return std::make_pair(expandedByte, false);
168 }
169 
170 static void expandTabs(std::string &SourceLine, unsigned TabStop) {
171   size_t i = SourceLine.size();
172   while (i>0) {
173     i--;
174     if (SourceLine[i]!='\t')
175       continue;
176     size_t tmp_i = i;
177     std::pair<SmallString<16>,bool> res
178       = printableTextForNextCharacter(SourceLine, &tmp_i, TabStop);
179     SourceLine.replace(i, 1, res.first.c_str());
180   }
181 }
182 
183 /// This function takes a raw source line and produces a mapping from the bytes
184 ///  of the printable representation of the line to the columns those printable
185 ///  characters will appear at (numbering the first column as 0).
186 ///
187 /// If a byte 'i' corresponds to muliple columns (e.g. the byte contains a tab
188 ///  character) then the array will map that byte to the first column the
189 ///  tab appears at and the next value in the map will have been incremented
190 ///  more than once.
191 ///
192 /// If a byte is the first in a sequence of bytes that together map to a single
193 ///  entity in the output, then the array will map that byte to the appropriate
194 ///  column while the subsequent bytes will be -1.
195 ///
196 /// The last element in the array does not correspond to any byte in the input
197 ///  and instead is the number of columns needed to display the source
198 ///
199 /// example: (given a tabstop of 8)
200 ///
201 ///    "a \t \u3042" -> {0,1,2,8,9,-1,-1,11}
202 ///
203 ///  (\\u3042 is represented in UTF-8 by three bytes and takes two columns to
204 ///   display)
205 static void byteToColumn(StringRef SourceLine, unsigned TabStop,
206                          SmallVectorImpl<int> &out) {
207   out.clear();
208 
209   if (SourceLine.empty()) {
210     out.resize(1u,0);
211     return;
212   }
213 
214   out.resize(SourceLine.size()+1, -1);
215 
216   int columns = 0;
217   size_t i = 0;
218   while (i<SourceLine.size()) {
219     out[i] = columns;
220     std::pair<SmallString<16>,bool> res
221       = printableTextForNextCharacter(SourceLine, &i, TabStop);
222     columns += llvm::sys::locale::columnWidth(res.first);
223   }
224   out.back() = columns;
225 }
226 
227 /// This function takes a raw source line and produces a mapping from columns
228 ///  to the byte of the source line that produced the character displaying at
229 ///  that column. This is the inverse of the mapping produced by byteToColumn()
230 ///
231 /// The last element in the array is the number of bytes in the source string
232 ///
233 /// example: (given a tabstop of 8)
234 ///
235 ///    "a \t \u3042" -> {0,1,2,-1,-1,-1,-1,-1,3,4,-1,7}
236 ///
237 ///  (\\u3042 is represented in UTF-8 by three bytes and takes two columns to
238 ///   display)
239 static void columnToByte(StringRef SourceLine, unsigned TabStop,
240                          SmallVectorImpl<int> &out) {
241   out.clear();
242 
243   if (SourceLine.empty()) {
244     out.resize(1u, 0);
245     return;
246   }
247 
248   int columns = 0;
249   size_t i = 0;
250   while (i<SourceLine.size()) {
251     out.resize(columns+1, -1);
252     out.back() = i;
253     std::pair<SmallString<16>,bool> res
254       = printableTextForNextCharacter(SourceLine, &i, TabStop);
255     columns += llvm::sys::locale::columnWidth(res.first);
256   }
257   out.resize(columns+1, -1);
258   out.back() = i;
259 }
260 
261 struct SourceColumnMap {
262   SourceColumnMap(StringRef SourceLine, unsigned TabStop)
263   : m_SourceLine(SourceLine) {
264 
265     ::byteToColumn(SourceLine, TabStop, m_byteToColumn);
266     ::columnToByte(SourceLine, TabStop, m_columnToByte);
267 
268     assert(m_byteToColumn.size()==SourceLine.size()+1);
269     assert(0 < m_byteToColumn.size() && 0 < m_columnToByte.size());
270     assert(m_byteToColumn.size()
271            == static_cast<unsigned>(m_columnToByte.back()+1));
272     assert(static_cast<unsigned>(m_byteToColumn.back()+1)
273            == m_columnToByte.size());
274   }
275   int columns() const { return m_byteToColumn.back(); }
276   int bytes() const { return m_columnToByte.back(); }
277 
278   /// \brief Map a byte to the column which it is at the start of, or return -1
279   /// if it is not at the start of a column (for a UTF-8 trailing byte).
280   int byteToColumn(int n) const {
281     assert(0<=n && n<static_cast<int>(m_byteToColumn.size()));
282     return m_byteToColumn[n];
283   }
284 
285   /// \brief Map a byte to the first column which contains it.
286   int byteToContainingColumn(int N) const {
287     assert(0 <= N && N < static_cast<int>(m_byteToColumn.size()));
288     while (m_byteToColumn[N] == -1)
289       --N;
290     return m_byteToColumn[N];
291   }
292 
293   /// \brief Map a column to the byte which starts the column, or return -1 if
294   /// the column the second or subsequent column of an expanded tab or similar
295   /// multi-column entity.
296   int columnToByte(int n) const {
297     assert(0<=n && n<static_cast<int>(m_columnToByte.size()));
298     return m_columnToByte[n];
299   }
300 
301   /// \brief Map from a byte index to the next byte which starts a column.
302   int startOfNextColumn(int N) const {
303     assert(0 <= N && N < static_cast<int>(m_columnToByte.size() - 1));
304     while (byteToColumn(++N) == -1) {}
305     return N;
306   }
307 
308   /// \brief Map from a byte index to the previous byte which starts a column.
309   int startOfPreviousColumn(int N) const {
310     assert(0 < N && N < static_cast<int>(m_columnToByte.size()));
311     while (byteToColumn(N--) == -1) {}
312     return N;
313   }
314 
315   StringRef getSourceLine() const {
316     return m_SourceLine;
317   }
318 
319 private:
320   const std::string m_SourceLine;
321   SmallVector<int,200> m_byteToColumn;
322   SmallVector<int,200> m_columnToByte;
323 };
324 
325 // used in assert in selectInterestingSourceRegion()
326 namespace {
327 struct char_out_of_range {
328   const char lower,upper;
329   char_out_of_range(char lower, char upper) :
330     lower(lower), upper(upper) {}
331   bool operator()(char c) { return c < lower || upper < c; }
332 };
333 }
334 
335 /// \brief When the source code line we want to print is too long for
336 /// the terminal, select the "interesting" region.
337 static void selectInterestingSourceRegion(std::string &SourceLine,
338                                           std::string &CaretLine,
339                                           std::string &FixItInsertionLine,
340                                           unsigned Columns,
341                                           const SourceColumnMap &map) {
342   unsigned MaxColumns = std::max<unsigned>(map.columns(),
343                                            std::max(CaretLine.size(),
344                                                     FixItInsertionLine.size()));
345   // if the number of columns is less than the desired number we're done
346   if (MaxColumns <= Columns)
347     return;
348 
349   // no special characters allowed in CaretLine or FixItInsertionLine
350   assert(CaretLine.end() ==
351          std::find_if(CaretLine.begin(), CaretLine.end(),
352          char_out_of_range(' ','~')));
353   assert(FixItInsertionLine.end() ==
354          std::find_if(FixItInsertionLine.begin(), FixItInsertionLine.end(),
355          char_out_of_range(' ','~')));
356 
357   // Find the slice that we need to display the full caret line
358   // correctly.
359   unsigned CaretStart = 0, CaretEnd = CaretLine.size();
360   for (; CaretStart != CaretEnd; ++CaretStart)
361     if (!isspace(static_cast<unsigned char>(CaretLine[CaretStart])))
362       break;
363 
364   for (; CaretEnd != CaretStart; --CaretEnd)
365     if (!isspace(static_cast<unsigned char>(CaretLine[CaretEnd - 1])))
366       break;
367 
368   // caret has already been inserted into CaretLine so the above whitespace
369   // check is guaranteed to include the caret
370 
371   // If we have a fix-it line, make sure the slice includes all of the
372   // fix-it information.
373   if (!FixItInsertionLine.empty()) {
374     unsigned FixItStart = 0, FixItEnd = FixItInsertionLine.size();
375     for (; FixItStart != FixItEnd; ++FixItStart)
376       if (!isspace(static_cast<unsigned char>(FixItInsertionLine[FixItStart])))
377         break;
378 
379     for (; FixItEnd != FixItStart; --FixItEnd)
380       if (!isspace(static_cast<unsigned char>(FixItInsertionLine[FixItEnd - 1])))
381         break;
382 
383     CaretStart = std::min(FixItStart, CaretStart);
384     CaretEnd = std::max(FixItEnd, CaretEnd);
385   }
386 
387   // CaretEnd may have been set at the middle of a character
388   // If it's not at a character's first column then advance it past the current
389   //   character.
390   while (static_cast<int>(CaretEnd) < map.columns() &&
391          -1 == map.columnToByte(CaretEnd))
392     ++CaretEnd;
393 
394   assert((static_cast<int>(CaretStart) > map.columns() ||
395           -1!=map.columnToByte(CaretStart)) &&
396          "CaretStart must not point to a column in the middle of a source"
397          " line character");
398   assert((static_cast<int>(CaretEnd) > map.columns() ||
399           -1!=map.columnToByte(CaretEnd)) &&
400          "CaretEnd must not point to a column in the middle of a source line"
401          " character");
402 
403   // CaretLine[CaretStart, CaretEnd) contains all of the interesting
404   // parts of the caret line. While this slice is smaller than the
405   // number of columns we have, try to grow the slice to encompass
406   // more context.
407 
408   unsigned SourceStart = map.columnToByte(std::min<unsigned>(CaretStart,
409                                                              map.columns()));
410   unsigned SourceEnd = map.columnToByte(std::min<unsigned>(CaretEnd,
411                                                            map.columns()));
412 
413   unsigned CaretColumnsOutsideSource = CaretEnd-CaretStart
414     - (map.byteToColumn(SourceEnd)-map.byteToColumn(SourceStart));
415 
416   char const *front_ellipse = "  ...";
417   char const *front_space   = "     ";
418   char const *back_ellipse = "...";
419   unsigned ellipses_space = strlen(front_ellipse) + strlen(back_ellipse);
420 
421   unsigned TargetColumns = Columns;
422   // Give us extra room for the ellipses
423   //  and any of the caret line that extends past the source
424   if (TargetColumns > ellipses_space+CaretColumnsOutsideSource)
425     TargetColumns -= ellipses_space+CaretColumnsOutsideSource;
426 
427   while (SourceStart>0 || SourceEnd<SourceLine.size()) {
428     bool ExpandedRegion = false;
429 
430     if (SourceStart>0) {
431       unsigned NewStart = SourceStart-1;
432 
433       // Skip over any whitespace we see here; we're looking for
434       // another bit of interesting text.
435       // FIXME: Detect non-ASCII whitespace characters too.
436       while (NewStart &&
437              isspace(static_cast<unsigned char>(SourceLine[NewStart])))
438         NewStart = map.startOfPreviousColumn(NewStart);
439 
440       // Skip over this bit of "interesting" text.
441       while (NewStart) {
442         unsigned Prev = map.startOfPreviousColumn(NewStart);
443         if (isspace(static_cast<unsigned char>(SourceLine[Prev])))
444           break;
445         NewStart = Prev;
446       }
447 
448       assert(map.byteToColumn(NewStart) != -1);
449       unsigned NewColumns = map.byteToColumn(SourceEnd) -
450                               map.byteToColumn(NewStart);
451       if (NewColumns <= TargetColumns) {
452         SourceStart = NewStart;
453         ExpandedRegion = true;
454       }
455     }
456 
457     if (SourceEnd<SourceLine.size()) {
458       unsigned NewEnd = SourceEnd+1;
459 
460       // Skip over any whitespace we see here; we're looking for
461       // another bit of interesting text.
462       // FIXME: Detect non-ASCII whitespace characters too.
463       while (NewEnd < SourceLine.size() &&
464              isspace(static_cast<unsigned char>(SourceLine[NewEnd])))
465         NewEnd = map.startOfNextColumn(NewEnd);
466 
467       // Skip over this bit of "interesting" text.
468       while (NewEnd < SourceLine.size() &&
469              !isspace(static_cast<unsigned char>(SourceLine[NewEnd])))
470         NewEnd = map.startOfNextColumn(NewEnd);
471 
472       assert(map.byteToColumn(NewEnd) != -1);
473       unsigned NewColumns = map.byteToColumn(NewEnd) -
474                               map.byteToColumn(SourceStart);
475       if (NewColumns <= TargetColumns) {
476         SourceEnd = NewEnd;
477         ExpandedRegion = true;
478       }
479     }
480 
481     if (!ExpandedRegion)
482       break;
483   }
484 
485   CaretStart = map.byteToColumn(SourceStart);
486   CaretEnd = map.byteToColumn(SourceEnd) + CaretColumnsOutsideSource;
487 
488   // [CaretStart, CaretEnd) is the slice we want. Update the various
489   // output lines to show only this slice, with two-space padding
490   // before the lines so that it looks nicer.
491 
492   assert(CaretStart!=(unsigned)-1 && CaretEnd!=(unsigned)-1 &&
493          SourceStart!=(unsigned)-1 && SourceEnd!=(unsigned)-1);
494   assert(SourceStart <= SourceEnd);
495   assert(CaretStart <= CaretEnd);
496 
497   unsigned BackColumnsRemoved
498     = map.byteToColumn(SourceLine.size())-map.byteToColumn(SourceEnd);
499   unsigned FrontColumnsRemoved = CaretStart;
500   unsigned ColumnsKept = CaretEnd-CaretStart;
501 
502   // We checked up front that the line needed truncation
503   assert(FrontColumnsRemoved+ColumnsKept+BackColumnsRemoved > Columns);
504 
505   // The line needs some trunctiona, and we'd prefer to keep the front
506   //  if possible, so remove the back
507   if (BackColumnsRemoved)
508     SourceLine.replace(SourceEnd, std::string::npos, back_ellipse);
509 
510   // If that's enough then we're done
511   if (FrontColumnsRemoved+ColumnsKept <= Columns)
512     return;
513 
514   // Otherwise remove the front as well
515   if (FrontColumnsRemoved) {
516     SourceLine.replace(0, SourceStart, front_ellipse);
517     CaretLine.replace(0, CaretStart, front_space);
518     if (!FixItInsertionLine.empty())
519       FixItInsertionLine.replace(0, CaretStart, front_space);
520   }
521 }
522 
523 /// \brief Skip over whitespace in the string, starting at the given
524 /// index.
525 ///
526 /// \returns The index of the first non-whitespace character that is
527 /// greater than or equal to Idx or, if no such character exists,
528 /// returns the end of the string.
529 static unsigned skipWhitespace(unsigned Idx, StringRef Str, unsigned Length) {
530   while (Idx < Length && isspace(Str[Idx]))
531     ++Idx;
532   return Idx;
533 }
534 
535 /// \brief If the given character is the start of some kind of
536 /// balanced punctuation (e.g., quotes or parentheses), return the
537 /// character that will terminate the punctuation.
538 ///
539 /// \returns The ending punctuation character, if any, or the NULL
540 /// character if the input character does not start any punctuation.
541 static inline char findMatchingPunctuation(char c) {
542   switch (c) {
543   case '\'': return '\'';
544   case '`': return '\'';
545   case '"':  return '"';
546   case '(':  return ')';
547   case '[': return ']';
548   case '{': return '}';
549   default: break;
550   }
551 
552   return 0;
553 }
554 
555 /// \brief Find the end of the word starting at the given offset
556 /// within a string.
557 ///
558 /// \returns the index pointing one character past the end of the
559 /// word.
560 static unsigned findEndOfWord(unsigned Start, StringRef Str,
561                               unsigned Length, unsigned Column,
562                               unsigned Columns) {
563   assert(Start < Str.size() && "Invalid start position!");
564   unsigned End = Start + 1;
565 
566   // If we are already at the end of the string, take that as the word.
567   if (End == Str.size())
568     return End;
569 
570   // Determine if the start of the string is actually opening
571   // punctuation, e.g., a quote or parentheses.
572   char EndPunct = findMatchingPunctuation(Str[Start]);
573   if (!EndPunct) {
574     // This is a normal word. Just find the first space character.
575     while (End < Length && !isspace(Str[End]))
576       ++End;
577     return End;
578   }
579 
580   // We have the start of a balanced punctuation sequence (quotes,
581   // parentheses, etc.). Determine the full sequence is.
582   SmallString<16> PunctuationEndStack;
583   PunctuationEndStack.push_back(EndPunct);
584   while (End < Length && !PunctuationEndStack.empty()) {
585     if (Str[End] == PunctuationEndStack.back())
586       PunctuationEndStack.pop_back();
587     else if (char SubEndPunct = findMatchingPunctuation(Str[End]))
588       PunctuationEndStack.push_back(SubEndPunct);
589 
590     ++End;
591   }
592 
593   // Find the first space character after the punctuation ended.
594   while (End < Length && !isspace(Str[End]))
595     ++End;
596 
597   unsigned PunctWordLength = End - Start;
598   if (// If the word fits on this line
599       Column + PunctWordLength <= Columns ||
600       // ... or the word is "short enough" to take up the next line
601       // without too much ugly white space
602       PunctWordLength < Columns/3)
603     return End; // Take the whole thing as a single "word".
604 
605   // The whole quoted/parenthesized string is too long to print as a
606   // single "word". Instead, find the "word" that starts just after
607   // the punctuation and use that end-point instead. This will recurse
608   // until it finds something small enough to consider a word.
609   return findEndOfWord(Start + 1, Str, Length, Column + 1, Columns);
610 }
611 
612 /// \brief Print the given string to a stream, word-wrapping it to
613 /// some number of columns in the process.
614 ///
615 /// \param OS the stream to which the word-wrapping string will be
616 /// emitted.
617 /// \param Str the string to word-wrap and output.
618 /// \param Columns the number of columns to word-wrap to.
619 /// \param Column the column number at which the first character of \p
620 /// Str will be printed. This will be non-zero when part of the first
621 /// line has already been printed.
622 /// \param Bold if the current text should be bold
623 /// \param Indentation the number of spaces to indent any lines beyond
624 /// the first line.
625 /// \returns true if word-wrapping was required, or false if the
626 /// string fit on the first line.
627 static bool printWordWrapped(raw_ostream &OS, StringRef Str,
628                              unsigned Columns,
629                              unsigned Column = 0,
630                              bool Bold = false,
631                              unsigned Indentation = WordWrapIndentation) {
632   const unsigned Length = std::min(Str.find('\n'), Str.size());
633   bool TextNormal = true;
634 
635   // The string used to indent each line.
636   SmallString<16> IndentStr;
637   IndentStr.assign(Indentation, ' ');
638   bool Wrapped = false;
639   for (unsigned WordStart = 0, WordEnd; WordStart < Length;
640        WordStart = WordEnd) {
641     // Find the beginning of the next word.
642     WordStart = skipWhitespace(WordStart, Str, Length);
643     if (WordStart == Length)
644       break;
645 
646     // Find the end of this word.
647     WordEnd = findEndOfWord(WordStart, Str, Length, Column, Columns);
648 
649     // Does this word fit on the current line?
650     unsigned WordLength = WordEnd - WordStart;
651     if (Column + WordLength < Columns) {
652       // This word fits on the current line; print it there.
653       if (WordStart) {
654         OS << ' ';
655         Column += 1;
656       }
657       applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength),
658                                 TextNormal, Bold);
659       Column += WordLength;
660       continue;
661     }
662 
663     // This word does not fit on the current line, so wrap to the next
664     // line.
665     OS << '\n';
666     OS.write(&IndentStr[0], Indentation);
667     applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength),
668                               TextNormal, Bold);
669     Column = Indentation + WordLength;
670     Wrapped = true;
671   }
672 
673   // Append any remaning text from the message with its existing formatting.
674   applyTemplateHighlighting(OS, Str.substr(Length), TextNormal, Bold);
675 
676   assert(TextNormal && "Text highlighted at end of diagnostic message.");
677 
678   return Wrapped;
679 }
680 
681 TextDiagnostic::TextDiagnostic(raw_ostream &OS,
682                                const LangOptions &LangOpts,
683                                const DiagnosticOptions &DiagOpts)
684   : DiagnosticRenderer(LangOpts, DiagOpts), OS(OS) {}
685 
686 TextDiagnostic::~TextDiagnostic() {}
687 
688 void
689 TextDiagnostic::emitDiagnosticMessage(SourceLocation Loc,
690                                       PresumedLoc PLoc,
691                                       DiagnosticsEngine::Level Level,
692                                       StringRef Message,
693                                       ArrayRef<clang::CharSourceRange> Ranges,
694                                       const SourceManager *SM,
695                                       DiagOrStoredDiag D) {
696   uint64_t StartOfLocationInfo = OS.tell();
697 
698   // Emit the location of this particular diagnostic.
699   if (Loc.isValid())
700     emitDiagnosticLoc(Loc, PLoc, Level, Ranges, *SM);
701 
702   if (DiagOpts.ShowColors)
703     OS.resetColor();
704 
705   printDiagnosticLevel(OS, Level, DiagOpts.ShowColors);
706   printDiagnosticMessage(OS, Level, Message,
707                          OS.tell() - StartOfLocationInfo,
708                          DiagOpts.MessageLength, DiagOpts.ShowColors);
709 }
710 
711 /*static*/ void
712 TextDiagnostic::printDiagnosticLevel(raw_ostream &OS,
713                                      DiagnosticsEngine::Level Level,
714                                      bool ShowColors) {
715   if (ShowColors) {
716     // Print diagnostic category in bold and color
717     switch (Level) {
718     case DiagnosticsEngine::Ignored:
719       llvm_unreachable("Invalid diagnostic type");
720     case DiagnosticsEngine::Note:    OS.changeColor(noteColor, true); break;
721     case DiagnosticsEngine::Warning: OS.changeColor(warningColor, true); break;
722     case DiagnosticsEngine::Error:   OS.changeColor(errorColor, true); break;
723     case DiagnosticsEngine::Fatal:   OS.changeColor(fatalColor, true); break;
724     }
725   }
726 
727   switch (Level) {
728   case DiagnosticsEngine::Ignored:
729     llvm_unreachable("Invalid diagnostic type");
730   case DiagnosticsEngine::Note:    OS << "note: "; break;
731   case DiagnosticsEngine::Warning: OS << "warning: "; break;
732   case DiagnosticsEngine::Error:   OS << "error: "; break;
733   case DiagnosticsEngine::Fatal:   OS << "fatal error: "; break;
734   }
735 
736   if (ShowColors)
737     OS.resetColor();
738 }
739 
740 /*static*/ void
741 TextDiagnostic::printDiagnosticMessage(raw_ostream &OS,
742                                        DiagnosticsEngine::Level Level,
743                                        StringRef Message,
744                                        unsigned CurrentColumn, unsigned Columns,
745                                        bool ShowColors) {
746   bool Bold = false;
747   if (ShowColors) {
748     // Print warnings, errors and fatal errors in bold, no color
749     switch (Level) {
750     case DiagnosticsEngine::Warning:
751     case DiagnosticsEngine::Error:
752     case DiagnosticsEngine::Fatal:
753       OS.changeColor(savedColor, true);
754       Bold = true;
755       break;
756     default: break; //don't bold notes
757     }
758   }
759 
760   if (Columns)
761     printWordWrapped(OS, Message, Columns, CurrentColumn, Bold);
762   else {
763     bool Normal = true;
764     applyTemplateHighlighting(OS, Message, Normal, Bold);
765     assert(Normal && "Formatting should have returned to normal");
766   }
767 
768   if (ShowColors)
769     OS.resetColor();
770   OS << '\n';
771 }
772 
773 /// \brief Print out the file/line/column information and include trace.
774 ///
775 /// This method handlen the emission of the diagnostic location information.
776 /// This includes extracting as much location information as is present for
777 /// the diagnostic and printing it, as well as any include stack or source
778 /// ranges necessary.
779 void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
780                                        DiagnosticsEngine::Level Level,
781                                        ArrayRef<CharSourceRange> Ranges,
782                                        const SourceManager &SM) {
783   if (PLoc.isInvalid()) {
784     // At least print the file name if available:
785     FileID FID = SM.getFileID(Loc);
786     if (!FID.isInvalid()) {
787       const FileEntry* FE = SM.getFileEntryForID(FID);
788       if (FE && FE->getName()) {
789         OS << FE->getName();
790         if (FE->getDevice() == 0 && FE->getInode() == 0
791             && FE->getFileMode() == 0) {
792           // in PCH is a guess, but a good one:
793           OS << " (in PCH)";
794         }
795         OS << ": ";
796       }
797     }
798     return;
799   }
800   unsigned LineNo = PLoc.getLine();
801 
802   if (!DiagOpts.ShowLocation)
803     return;
804 
805   if (DiagOpts.ShowColors)
806     OS.changeColor(savedColor, true);
807 
808   OS << PLoc.getFilename();
809   switch (DiagOpts.Format) {
810   case DiagnosticOptions::Clang: OS << ':'  << LineNo; break;
811   case DiagnosticOptions::Msvc:  OS << '('  << LineNo; break;
812   case DiagnosticOptions::Vi:    OS << " +" << LineNo; break;
813   }
814 
815   if (DiagOpts.ShowColumn)
816     // Compute the column number.
817     if (unsigned ColNo = PLoc.getColumn()) {
818       if (DiagOpts.Format == DiagnosticOptions::Msvc) {
819         OS << ',';
820         ColNo--;
821       } else
822         OS << ':';
823       OS << ColNo;
824     }
825   switch (DiagOpts.Format) {
826   case DiagnosticOptions::Clang:
827   case DiagnosticOptions::Vi:    OS << ':';    break;
828   case DiagnosticOptions::Msvc:  OS << ") : "; break;
829   }
830 
831   if (DiagOpts.ShowSourceRanges && !Ranges.empty()) {
832     FileID CaretFileID =
833       SM.getFileID(SM.getExpansionLoc(Loc));
834     bool PrintedRange = false;
835 
836     for (ArrayRef<CharSourceRange>::const_iterator RI = Ranges.begin(),
837          RE = Ranges.end();
838          RI != RE; ++RI) {
839       // Ignore invalid ranges.
840       if (!RI->isValid()) continue;
841 
842       SourceLocation B = SM.getExpansionLoc(RI->getBegin());
843       SourceLocation E = SM.getExpansionLoc(RI->getEnd());
844 
845       // If the End location and the start location are the same and are a
846       // macro location, then the range was something that came from a
847       // macro expansion or _Pragma.  If this is an object-like macro, the
848       // best we can do is to highlight the range.  If this is a
849       // function-like macro, we'd also like to highlight the arguments.
850       if (B == E && RI->getEnd().isMacroID())
851         E = SM.getExpansionRange(RI->getEnd()).second;
852 
853       std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
854       std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
855 
856       // If the start or end of the range is in another file, just discard
857       // it.
858       if (BInfo.first != CaretFileID || EInfo.first != CaretFileID)
859         continue;
860 
861       // Add in the length of the token, so that we cover multi-char
862       // tokens.
863       unsigned TokSize = 0;
864       if (RI->isTokenRange())
865         TokSize = Lexer::MeasureTokenLength(E, SM, LangOpts);
866 
867       OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':'
868         << SM.getColumnNumber(BInfo.first, BInfo.second) << '-'
869         << SM.getLineNumber(EInfo.first, EInfo.second) << ':'
870         << (SM.getColumnNumber(EInfo.first, EInfo.second)+TokSize)
871         << '}';
872       PrintedRange = true;
873     }
874 
875     if (PrintedRange)
876       OS << ':';
877   }
878   OS << ' ';
879 }
880 
881 void TextDiagnostic::emitBasicNote(StringRef Message) {
882   // FIXME: Emit this as a real note diagnostic.
883   // FIXME: Format an actual diagnostic rather than a hard coded string.
884   OS << "note: " << Message << "\n";
885 }
886 
887 void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
888                                          PresumedLoc PLoc,
889                                          const SourceManager &SM) {
890   if (DiagOpts.ShowLocation)
891     OS << "In file included from " << PLoc.getFilename() << ':'
892        << PLoc.getLine() << ":\n";
893   else
894     OS << "In included file:\n";
895 }
896 
897 /// \brief Emit a code snippet and caret line.
898 ///
899 /// This routine emits a single line's code snippet and caret line..
900 ///
901 /// \param Loc The location for the caret.
902 /// \param Ranges The underlined ranges for this code snippet.
903 /// \param Hints The FixIt hints active for this diagnostic.
904 void TextDiagnostic::emitSnippetAndCaret(
905     SourceLocation Loc, DiagnosticsEngine::Level Level,
906     SmallVectorImpl<CharSourceRange>& Ranges,
907     ArrayRef<FixItHint> Hints,
908     const SourceManager &SM) {
909   assert(!Loc.isInvalid() && "must have a valid source location here");
910   assert(Loc.isFileID() && "must have a file location here");
911 
912   // If caret diagnostics are enabled and we have location, we want to
913   // emit the caret.  However, we only do this if the location moved
914   // from the last diagnostic, if the last diagnostic was a note that
915   // was part of a different warning or error diagnostic, or if the
916   // diagnostic has ranges.  We don't want to emit the same caret
917   // multiple times if one loc has multiple diagnostics.
918   if (!DiagOpts.ShowCarets)
919     return;
920   if (Loc == LastLoc && Ranges.empty() && Hints.empty() &&
921       (LastLevel != DiagnosticsEngine::Note || Level == LastLevel))
922     return;
923 
924   // Decompose the location into a FID/Offset pair.
925   std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
926   FileID FID = LocInfo.first;
927   unsigned FileOffset = LocInfo.second;
928 
929   // Get information about the buffer it points into.
930   bool Invalid = false;
931   const char *BufStart = SM.getBufferData(FID, &Invalid).data();
932   if (Invalid)
933     return;
934 
935   unsigned LineNo = SM.getLineNumber(FID, FileOffset);
936   unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
937 
938   // Rewind from the current position to the start of the line.
939   const char *TokPtr = BufStart+FileOffset;
940   const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based.
941 
942 
943   // Compute the line end.  Scan forward from the error position to the end of
944   // the line.
945   const char *LineEnd = TokPtr;
946   while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')
947     ++LineEnd;
948 
949   // Copy the line of code into an std::string for ease of manipulation.
950   std::string SourceLine(LineStart, LineEnd);
951 
952   // Create a line for the caret that is filled with spaces that is the same
953   // length as the line of source code.
954   std::string CaretLine(LineEnd-LineStart, ' ');
955 
956   const SourceColumnMap sourceColMap(SourceLine, DiagOpts.TabStop);
957 
958   // Highlight all of the characters covered by Ranges with ~ characters.
959   for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
960                                                   E = Ranges.end();
961        I != E; ++I)
962     highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM);
963 
964   // Next, insert the caret itself.
965   ColNo = sourceColMap.byteToContainingColumn(ColNo-1);
966   if (CaretLine.size()<ColNo+1)
967     CaretLine.resize(ColNo+1, ' ');
968   CaretLine[ColNo] = '^';
969 
970   std::string FixItInsertionLine = buildFixItInsertionLine(LineNo,
971                                                            sourceColMap,
972                                                            Hints, SM);
973 
974   // If the source line is too long for our terminal, select only the
975   // "interesting" source region within that line.
976   unsigned Columns = DiagOpts.MessageLength;
977   if (Columns)
978     selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine,
979                                   Columns, sourceColMap);
980 
981   // If we are in -fdiagnostics-print-source-range-info mode, we are trying
982   // to produce easily machine parsable output.  Add a space before the
983   // source line and the caret to make it trivial to tell the main diagnostic
984   // line from what the user is intended to see.
985   if (DiagOpts.ShowSourceRanges) {
986     SourceLine = ' ' + SourceLine;
987     CaretLine = ' ' + CaretLine;
988   }
989 
990   // Finally, remove any blank spaces from the end of CaretLine.
991   while (CaretLine[CaretLine.size()-1] == ' ')
992     CaretLine.erase(CaretLine.end()-1);
993 
994   // Emit what we have computed.
995   emitSnippet(SourceLine);
996 
997   if (DiagOpts.ShowColors)
998     OS.changeColor(caretColor, true);
999   OS << CaretLine << '\n';
1000   if (DiagOpts.ShowColors)
1001     OS.resetColor();
1002 
1003   if (!FixItInsertionLine.empty()) {
1004     if (DiagOpts.ShowColors)
1005       // Print fixit line in color
1006       OS.changeColor(fixitColor, false);
1007     if (DiagOpts.ShowSourceRanges)
1008       OS << ' ';
1009     OS << FixItInsertionLine << '\n';
1010     if (DiagOpts.ShowColors)
1011       OS.resetColor();
1012   }
1013 
1014   // Print out any parseable fixit information requested by the options.
1015   emitParseableFixits(Hints, SM);
1016 }
1017 
1018 void TextDiagnostic::emitSnippet(StringRef line) {
1019   if (line.empty())
1020     return;
1021 
1022   size_t i = 0;
1023 
1024   std::string to_print;
1025   bool print_reversed = false;
1026 
1027   while (i<line.size()) {
1028     std::pair<SmallString<16>,bool> res
1029         = printableTextForNextCharacter(line, &i, DiagOpts.TabStop);
1030     bool was_printable = res.second;
1031 
1032     if (DiagOpts.ShowColors && was_printable == print_reversed) {
1033       if (print_reversed)
1034         OS.reverseColor();
1035       OS << to_print;
1036       to_print.clear();
1037       if (DiagOpts.ShowColors)
1038         OS.resetColor();
1039     }
1040 
1041     print_reversed = !was_printable;
1042     to_print += res.first.str();
1043   }
1044 
1045   if (print_reversed && DiagOpts.ShowColors)
1046     OS.reverseColor();
1047   OS << to_print;
1048   if (print_reversed && DiagOpts.ShowColors)
1049     OS.resetColor();
1050 
1051   OS << '\n';
1052 }
1053 
1054 /// \brief Highlight a SourceRange (with ~'s) for any characters on LineNo.
1055 void TextDiagnostic::highlightRange(const CharSourceRange &R,
1056                                     unsigned LineNo, FileID FID,
1057                                     const SourceColumnMap &map,
1058                                     std::string &CaretLine,
1059                                     const SourceManager &SM) {
1060   if (!R.isValid()) return;
1061 
1062   SourceLocation Begin = SM.getExpansionLoc(R.getBegin());
1063   SourceLocation End = SM.getExpansionLoc(R.getEnd());
1064 
1065   // If the End location and the start location are the same and are a macro
1066   // location, then the range was something that came from a macro expansion
1067   // or _Pragma.  If this is an object-like macro, the best we can do is to
1068   // highlight the range.  If this is a function-like macro, we'd also like to
1069   // highlight the arguments.
1070   if (Begin == End && R.getEnd().isMacroID())
1071     End = SM.getExpansionRange(R.getEnd()).second;
1072 
1073   unsigned StartLineNo = SM.getExpansionLineNumber(Begin);
1074   if (StartLineNo > LineNo || SM.getFileID(Begin) != FID)
1075     return;  // No intersection.
1076 
1077   unsigned EndLineNo = SM.getExpansionLineNumber(End);
1078   if (EndLineNo < LineNo || SM.getFileID(End) != FID)
1079     return;  // No intersection.
1080 
1081   // Compute the column number of the start.
1082   unsigned StartColNo = 0;
1083   if (StartLineNo == LineNo) {
1084     StartColNo = SM.getExpansionColumnNumber(Begin);
1085     if (StartColNo) --StartColNo;  // Zero base the col #.
1086   }
1087 
1088   // Compute the column number of the end.
1089   unsigned EndColNo = map.getSourceLine().size();
1090   if (EndLineNo == LineNo) {
1091     EndColNo = SM.getExpansionColumnNumber(End);
1092     if (EndColNo) {
1093       --EndColNo;  // Zero base the col #.
1094 
1095       // Add in the length of the token, so that we cover multi-char tokens if
1096       // this is a token range.
1097       if (R.isTokenRange())
1098         EndColNo += Lexer::MeasureTokenLength(End, SM, LangOpts);
1099     } else {
1100       EndColNo = CaretLine.size();
1101     }
1102   }
1103 
1104   assert(StartColNo <= EndColNo && "Invalid range!");
1105 
1106   // Check that a token range does not highlight only whitespace.
1107   if (R.isTokenRange()) {
1108     // Pick the first non-whitespace column.
1109     while (StartColNo < map.getSourceLine().size() &&
1110            (map.getSourceLine()[StartColNo] == ' ' ||
1111             map.getSourceLine()[StartColNo] == '\t'))
1112       StartColNo = map.startOfNextColumn(StartColNo);
1113 
1114     // Pick the last non-whitespace column.
1115     if (EndColNo > map.getSourceLine().size())
1116       EndColNo = map.getSourceLine().size();
1117     while (EndColNo-1 &&
1118            (map.getSourceLine()[EndColNo-1] == ' ' ||
1119             map.getSourceLine()[EndColNo-1] == '\t'))
1120       EndColNo = map.startOfPreviousColumn(EndColNo);
1121 
1122     // If the start/end passed each other, then we are trying to highlight a
1123     // range that just exists in whitespace, which must be some sort of other
1124     // bug.
1125     assert(StartColNo <= EndColNo && "Trying to highlight whitespace??");
1126   }
1127 
1128   assert(StartColNo <= map.getSourceLine().size() && "Invalid range!");
1129   assert(EndColNo <= map.getSourceLine().size() && "Invalid range!");
1130 
1131   // Fill the range with ~'s.
1132   StartColNo = map.byteToContainingColumn(StartColNo);
1133   EndColNo = map.byteToContainingColumn(EndColNo);
1134 
1135   assert(StartColNo <= EndColNo && "Invalid range!");
1136   if (CaretLine.size() < EndColNo)
1137     CaretLine.resize(EndColNo,' ');
1138   std::fill(CaretLine.begin()+StartColNo,CaretLine.begin()+EndColNo,'~');
1139 }
1140 
1141 std::string TextDiagnostic::buildFixItInsertionLine(
1142   unsigned LineNo,
1143   const SourceColumnMap &map,
1144   ArrayRef<FixItHint> Hints,
1145   const SourceManager &SM) {
1146 
1147   std::string FixItInsertionLine;
1148   if (Hints.empty() || !DiagOpts.ShowFixits)
1149     return FixItInsertionLine;
1150   unsigned PrevHintEndCol = 0;
1151 
1152   for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
1153        I != E; ++I) {
1154     if (!I->CodeToInsert.empty()) {
1155       // We have an insertion hint. Determine whether the inserted
1156       // code contains no newlines and is on the same line as the caret.
1157       std::pair<FileID, unsigned> HintLocInfo
1158         = SM.getDecomposedExpansionLoc(I->RemoveRange.getBegin());
1159       if (LineNo == SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) &&
1160           StringRef(I->CodeToInsert).find_first_of("\n\r") == StringRef::npos) {
1161         // Insert the new code into the line just below the code
1162         // that the user wrote.
1163         // Note: When modifying this function, be very careful about what is a
1164         // "column" (printed width, platform-dependent) and what is a
1165         // "byte offset" (SourceManager "column").
1166         unsigned HintByteOffset
1167           = SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second) - 1;
1168 
1169         // The hint must start inside the source or right at the end
1170         assert(HintByteOffset < static_cast<unsigned>(map.bytes())+1);
1171         unsigned HintCol = map.byteToContainingColumn(HintByteOffset);
1172 
1173         // If we inserted a long previous hint, push this one forwards, and add
1174         // an extra space to show that this is not part of the previous
1175         // completion. This is sort of the best we can do when two hints appear
1176         // to overlap.
1177         //
1178         // Note that if this hint is located immediately after the previous
1179         // hint, no space will be added, since the location is more important.
1180         if (HintCol < PrevHintEndCol)
1181           HintCol = PrevHintEndCol + 1;
1182 
1183         // FIXME: This function handles multibyte characters in the source, but
1184         // not in the fixits. This assertion is intended to catch unintended
1185         // use of multibyte characters in fixits. If we decide to do this, we'll
1186         // have to track separate byte widths for the source and fixit lines.
1187         assert((size_t)llvm::sys::locale::columnWidth(I->CodeToInsert) ==
1188                I->CodeToInsert.size());
1189 
1190         // This relies on one byte per column in our fixit hints.
1191         // This should NOT use HintByteOffset, because the source might have
1192         // Unicode characters in earlier columns.
1193         unsigned LastColumnModified = HintCol + I->CodeToInsert.size();
1194         if (LastColumnModified > FixItInsertionLine.size())
1195           FixItInsertionLine.resize(LastColumnModified, ' ');
1196 
1197         std::copy(I->CodeToInsert.begin(), I->CodeToInsert.end(),
1198                   FixItInsertionLine.begin() + HintCol);
1199 
1200         PrevHintEndCol = LastColumnModified;
1201       } else {
1202         FixItInsertionLine.clear();
1203         break;
1204       }
1205     }
1206   }
1207 
1208   expandTabs(FixItInsertionLine, DiagOpts.TabStop);
1209 
1210   return FixItInsertionLine;
1211 }
1212 
1213 void TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints,
1214                                          const SourceManager &SM) {
1215   if (!DiagOpts.ShowParseableFixits)
1216     return;
1217 
1218   // We follow FixItRewriter's example in not (yet) handling
1219   // fix-its in macros.
1220   for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
1221        I != E; ++I) {
1222     if (I->RemoveRange.isInvalid() ||
1223         I->RemoveRange.getBegin().isMacroID() ||
1224         I->RemoveRange.getEnd().isMacroID())
1225       return;
1226   }
1227 
1228   for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
1229        I != E; ++I) {
1230     SourceLocation BLoc = I->RemoveRange.getBegin();
1231     SourceLocation ELoc = I->RemoveRange.getEnd();
1232 
1233     std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc);
1234     std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc);
1235 
1236     // Adjust for token ranges.
1237     if (I->RemoveRange.isTokenRange())
1238       EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, LangOpts);
1239 
1240     // We specifically do not do word-wrapping or tab-expansion here,
1241     // because this is supposed to be easy to parse.
1242     PresumedLoc PLoc = SM.getPresumedLoc(BLoc);
1243     if (PLoc.isInvalid())
1244       break;
1245 
1246     OS << "fix-it:\"";
1247     OS.write_escaped(PLoc.getFilename());
1248     OS << "\":{" << SM.getLineNumber(BInfo.first, BInfo.second)
1249       << ':' << SM.getColumnNumber(BInfo.first, BInfo.second)
1250       << '-' << SM.getLineNumber(EInfo.first, EInfo.second)
1251       << ':' << SM.getColumnNumber(EInfo.first, EInfo.second)
1252       << "}:\"";
1253     OS.write_escaped(I->CodeToInsert);
1254     OS << "\"\n";
1255   }
1256 }
1257