Home | History | Annotate | Download | only in Frontend
      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   int byteToColumn(int n) const {
    278     assert(0<=n && n<static_cast<int>(m_byteToColumn.size()));
    279     return m_byteToColumn[n];
    280   }
    281   int columnToByte(int n) const {
    282     assert(0<=n && n<static_cast<int>(m_columnToByte.size()));
    283     return m_columnToByte[n];
    284   }
    285   StringRef getSourceLine() const {
    286     return m_SourceLine;
    287   }
    288 
    289 private:
    290   const std::string m_SourceLine;
    291   SmallVector<int,200> m_byteToColumn;
    292   SmallVector<int,200> m_columnToByte;
    293 };
    294 
    295 // used in assert in selectInterestingSourceRegion()
    296 namespace {
    297 struct char_out_of_range {
    298   const char lower,upper;
    299   char_out_of_range(char lower, char upper) :
    300     lower(lower), upper(upper) {}
    301   bool operator()(char c) { return c < lower || upper < c; }
    302 };
    303 }
    304 
    305 /// \brief When the source code line we want to print is too long for
    306 /// the terminal, select the "interesting" region.
    307 static void selectInterestingSourceRegion(std::string &SourceLine,
    308                                           std::string &CaretLine,
    309                                           std::string &FixItInsertionLine,
    310                                           unsigned Columns,
    311                                           const SourceColumnMap &map) {
    312   unsigned MaxColumns = std::max<unsigned>(map.columns(),
    313                                            std::max(CaretLine.size(),
    314                                                     FixItInsertionLine.size()));
    315   // if the number of columns is less than the desired number we're done
    316   if (MaxColumns <= Columns)
    317     return;
    318 
    319   // no special characters allowed in CaretLine or FixItInsertionLine
    320   assert(CaretLine.end() ==
    321          std::find_if(CaretLine.begin(), CaretLine.end(),
    322          char_out_of_range(' ','~')));
    323   assert(FixItInsertionLine.end() ==
    324          std::find_if(FixItInsertionLine.begin(), FixItInsertionLine.end(),
    325          char_out_of_range(' ','~')));
    326 
    327   // Find the slice that we need to display the full caret line
    328   // correctly.
    329   unsigned CaretStart = 0, CaretEnd = CaretLine.size();
    330   for (; CaretStart != CaretEnd; ++CaretStart)
    331     if (!isspace(static_cast<unsigned char>(CaretLine[CaretStart])))
    332       break;
    333 
    334   for (; CaretEnd != CaretStart; --CaretEnd)
    335     if (!isspace(static_cast<unsigned char>(CaretLine[CaretEnd - 1])))
    336       break;
    337 
    338   // caret has already been inserted into CaretLine so the above whitespace
    339   // check is guaranteed to include the caret
    340 
    341   // If we have a fix-it line, make sure the slice includes all of the
    342   // fix-it information.
    343   if (!FixItInsertionLine.empty()) {
    344     unsigned FixItStart = 0, FixItEnd = FixItInsertionLine.size();
    345     for (; FixItStart != FixItEnd; ++FixItStart)
    346       if (!isspace(static_cast<unsigned char>(FixItInsertionLine[FixItStart])))
    347         break;
    348 
    349     for (; FixItEnd != FixItStart; --FixItEnd)
    350       if (!isspace(static_cast<unsigned char>(FixItInsertionLine[FixItEnd - 1])))
    351         break;
    352 
    353     CaretStart = std::min(FixItStart, CaretStart);
    354     CaretEnd = std::max(FixItEnd, CaretEnd);
    355   }
    356 
    357   // CaretEnd may have been set at the middle of a character
    358   // If it's not at a character's first column then advance it past the current
    359   //   character.
    360   while (static_cast<int>(CaretEnd) < map.columns() &&
    361          -1 == map.columnToByte(CaretEnd))
    362     ++CaretEnd;
    363 
    364   assert((static_cast<int>(CaretStart) > map.columns() ||
    365           -1!=map.columnToByte(CaretStart)) &&
    366          "CaretStart must not point to a column in the middle of a source"
    367          " line character");
    368   assert((static_cast<int>(CaretEnd) > map.columns() ||
    369           -1!=map.columnToByte(CaretEnd)) &&
    370          "CaretEnd must not point to a column in the middle of a source line"
    371          " character");
    372 
    373   // CaretLine[CaretStart, CaretEnd) contains all of the interesting
    374   // parts of the caret line. While this slice is smaller than the
    375   // number of columns we have, try to grow the slice to encompass
    376   // more context.
    377 
    378   unsigned SourceStart = map.columnToByte(std::min<unsigned>(CaretStart,
    379                                                              map.columns()));
    380   unsigned SourceEnd = map.columnToByte(std::min<unsigned>(CaretEnd,
    381                                                            map.columns()));
    382 
    383   unsigned CaretColumnsOutsideSource = CaretEnd-CaretStart
    384     - (map.byteToColumn(SourceEnd)-map.byteToColumn(SourceStart));
    385 
    386   char const *front_ellipse = "  ...";
    387   char const *front_space   = "     ";
    388   char const *back_ellipse = "...";
    389   unsigned ellipses_space = strlen(front_ellipse) + strlen(back_ellipse);
    390 
    391   unsigned TargetColumns = Columns;
    392   // Give us extra room for the ellipses
    393   //  and any of the caret line that extends past the source
    394   if (TargetColumns > ellipses_space+CaretColumnsOutsideSource)
    395     TargetColumns -= ellipses_space+CaretColumnsOutsideSource;
    396 
    397   while (SourceStart>0 || SourceEnd<SourceLine.size()) {
    398     bool ExpandedRegion = false;
    399 
    400     if (SourceStart>0) {
    401       unsigned NewStart = SourceStart-1;
    402 
    403       // Skip over any whitespace we see here; we're looking for
    404       // another bit of interesting text.
    405       while (NewStart &&
    406              (map.byteToColumn(NewStart)==-1 ||
    407              isspace(static_cast<unsigned char>(SourceLine[NewStart]))))
    408         --NewStart;
    409 
    410       // Skip over this bit of "interesting" text.
    411       while (NewStart &&
    412              (map.byteToColumn(NewStart)!=-1 &&
    413              !isspace(static_cast<unsigned char>(SourceLine[NewStart]))))
    414         --NewStart;
    415 
    416       // Move up to the non-whitespace character we just saw.
    417       if (NewStart)
    418         ++NewStart;
    419 
    420       unsigned NewColumns = map.byteToColumn(SourceEnd) -
    421                               map.byteToColumn(NewStart);
    422       if (NewColumns <= TargetColumns) {
    423         SourceStart = NewStart;
    424         ExpandedRegion = true;
    425       }
    426     }
    427 
    428     if (SourceEnd<SourceLine.size()) {
    429       unsigned NewEnd = SourceEnd+1;
    430 
    431       // Skip over any whitespace we see here; we're looking for
    432       // another bit of interesting text.
    433       while (NewEnd<SourceLine.size() &&
    434              (map.byteToColumn(NewEnd)==-1 ||
    435              isspace(static_cast<unsigned char>(SourceLine[NewEnd]))))
    436         ++NewEnd;
    437 
    438       // Skip over this bit of "interesting" text.
    439       while (NewEnd<SourceLine.size() &&
    440              (map.byteToColumn(NewEnd)!=-1 &&
    441              !isspace(static_cast<unsigned char>(SourceLine[NewEnd]))))
    442         ++NewEnd;
    443 
    444       unsigned NewColumns = map.byteToColumn(NewEnd) -
    445                               map.byteToColumn(SourceStart);
    446       if (NewColumns <= TargetColumns) {
    447         SourceEnd = NewEnd;
    448         ExpandedRegion = true;
    449       }
    450     }
    451 
    452     if (!ExpandedRegion)
    453       break;
    454   }
    455 
    456   CaretStart = map.byteToColumn(SourceStart);
    457   CaretEnd = map.byteToColumn(SourceEnd) + CaretColumnsOutsideSource;
    458 
    459   // [CaretStart, CaretEnd) is the slice we want. Update the various
    460   // output lines to show only this slice, with two-space padding
    461   // before the lines so that it looks nicer.
    462 
    463   assert(CaretStart!=(unsigned)-1 && CaretEnd!=(unsigned)-1 &&
    464          SourceStart!=(unsigned)-1 && SourceEnd!=(unsigned)-1);
    465   assert(SourceStart <= SourceEnd);
    466   assert(CaretStart <= CaretEnd);
    467 
    468   unsigned BackColumnsRemoved
    469     = map.byteToColumn(SourceLine.size())-map.byteToColumn(SourceEnd);
    470   unsigned FrontColumnsRemoved = CaretStart;
    471   unsigned ColumnsKept = CaretEnd-CaretStart;
    472 
    473   // We checked up front that the line needed truncation
    474   assert(FrontColumnsRemoved+ColumnsKept+BackColumnsRemoved > Columns);
    475 
    476   // The line needs some trunctiona, and we'd prefer to keep the front
    477   //  if possible, so remove the back
    478   if (BackColumnsRemoved)
    479     SourceLine.replace(SourceEnd, std::string::npos, back_ellipse);
    480 
    481   // If that's enough then we're done
    482   if (FrontColumnsRemoved+ColumnsKept <= Columns)
    483     return;
    484 
    485   // Otherwise remove the front as well
    486   if (FrontColumnsRemoved) {
    487     SourceLine.replace(0, SourceStart, front_ellipse);
    488     CaretLine.replace(0, CaretStart, front_space);
    489     if (!FixItInsertionLine.empty())
    490       FixItInsertionLine.replace(0, CaretStart, front_space);
    491   }
    492 }
    493 
    494 /// \brief Skip over whitespace in the string, starting at the given
    495 /// index.
    496 ///
    497 /// \returns The index of the first non-whitespace character that is
    498 /// greater than or equal to Idx or, if no such character exists,
    499 /// returns the end of the string.
    500 static unsigned skipWhitespace(unsigned Idx, StringRef Str, unsigned Length) {
    501   while (Idx < Length && isspace(Str[Idx]))
    502     ++Idx;
    503   return Idx;
    504 }
    505 
    506 /// \brief If the given character is the start of some kind of
    507 /// balanced punctuation (e.g., quotes or parentheses), return the
    508 /// character that will terminate the punctuation.
    509 ///
    510 /// \returns The ending punctuation character, if any, or the NULL
    511 /// character if the input character does not start any punctuation.
    512 static inline char findMatchingPunctuation(char c) {
    513   switch (c) {
    514   case '\'': return '\'';
    515   case '`': return '\'';
    516   case '"':  return '"';
    517   case '(':  return ')';
    518   case '[': return ']';
    519   case '{': return '}';
    520   default: break;
    521   }
    522 
    523   return 0;
    524 }
    525 
    526 /// \brief Find the end of the word starting at the given offset
    527 /// within a string.
    528 ///
    529 /// \returns the index pointing one character past the end of the
    530 /// word.
    531 static unsigned findEndOfWord(unsigned Start, StringRef Str,
    532                               unsigned Length, unsigned Column,
    533                               unsigned Columns) {
    534   assert(Start < Str.size() && "Invalid start position!");
    535   unsigned End = Start + 1;
    536 
    537   // If we are already at the end of the string, take that as the word.
    538   if (End == Str.size())
    539     return End;
    540 
    541   // Determine if the start of the string is actually opening
    542   // punctuation, e.g., a quote or parentheses.
    543   char EndPunct = findMatchingPunctuation(Str[Start]);
    544   if (!EndPunct) {
    545     // This is a normal word. Just find the first space character.
    546     while (End < Length && !isspace(Str[End]))
    547       ++End;
    548     return End;
    549   }
    550 
    551   // We have the start of a balanced punctuation sequence (quotes,
    552   // parentheses, etc.). Determine the full sequence is.
    553   SmallString<16> PunctuationEndStack;
    554   PunctuationEndStack.push_back(EndPunct);
    555   while (End < Length && !PunctuationEndStack.empty()) {
    556     if (Str[End] == PunctuationEndStack.back())
    557       PunctuationEndStack.pop_back();
    558     else if (char SubEndPunct = findMatchingPunctuation(Str[End]))
    559       PunctuationEndStack.push_back(SubEndPunct);
    560 
    561     ++End;
    562   }
    563 
    564   // Find the first space character after the punctuation ended.
    565   while (End < Length && !isspace(Str[End]))
    566     ++End;
    567 
    568   unsigned PunctWordLength = End - Start;
    569   if (// If the word fits on this line
    570       Column + PunctWordLength <= Columns ||
    571       // ... or the word is "short enough" to take up the next line
    572       // without too much ugly white space
    573       PunctWordLength < Columns/3)
    574     return End; // Take the whole thing as a single "word".
    575 
    576   // The whole quoted/parenthesized string is too long to print as a
    577   // single "word". Instead, find the "word" that starts just after
    578   // the punctuation and use that end-point instead. This will recurse
    579   // until it finds something small enough to consider a word.
    580   return findEndOfWord(Start + 1, Str, Length, Column + 1, Columns);
    581 }
    582 
    583 /// \brief Print the given string to a stream, word-wrapping it to
    584 /// some number of columns in the process.
    585 ///
    586 /// \param OS the stream to which the word-wrapping string will be
    587 /// emitted.
    588 /// \param Str the string to word-wrap and output.
    589 /// \param Columns the number of columns to word-wrap to.
    590 /// \param Column the column number at which the first character of \p
    591 /// Str will be printed. This will be non-zero when part of the first
    592 /// line has already been printed.
    593 /// \param Bold if the current text should be bold
    594 /// \param Indentation the number of spaces to indent any lines beyond
    595 /// the first line.
    596 /// \returns true if word-wrapping was required, or false if the
    597 /// string fit on the first line.
    598 static bool printWordWrapped(raw_ostream &OS, StringRef Str,
    599                              unsigned Columns,
    600                              unsigned Column = 0,
    601                              bool Bold = false,
    602                              unsigned Indentation = WordWrapIndentation) {
    603   const unsigned Length = std::min(Str.find('\n'), Str.size());
    604   bool TextNormal = true;
    605 
    606   // The string used to indent each line.
    607   SmallString<16> IndentStr;
    608   IndentStr.assign(Indentation, ' ');
    609   bool Wrapped = false;
    610   for (unsigned WordStart = 0, WordEnd; WordStart < Length;
    611        WordStart = WordEnd) {
    612     // Find the beginning of the next word.
    613     WordStart = skipWhitespace(WordStart, Str, Length);
    614     if (WordStart == Length)
    615       break;
    616 
    617     // Find the end of this word.
    618     WordEnd = findEndOfWord(WordStart, Str, Length, Column, Columns);
    619 
    620     // Does this word fit on the current line?
    621     unsigned WordLength = WordEnd - WordStart;
    622     if (Column + WordLength < Columns) {
    623       // This word fits on the current line; print it there.
    624       if (WordStart) {
    625         OS << ' ';
    626         Column += 1;
    627       }
    628       applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength),
    629                                 TextNormal, Bold);
    630       Column += WordLength;
    631       continue;
    632     }
    633 
    634     // This word does not fit on the current line, so wrap to the next
    635     // line.
    636     OS << '\n';
    637     OS.write(&IndentStr[0], Indentation);
    638     applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength),
    639                               TextNormal, Bold);
    640     Column = Indentation + WordLength;
    641     Wrapped = true;
    642   }
    643 
    644   // Append any remaning text from the message with its existing formatting.
    645   applyTemplateHighlighting(OS, Str.substr(Length), TextNormal, Bold);
    646 
    647   assert(TextNormal && "Text highlighted at end of diagnostic message.");
    648 
    649   return Wrapped;
    650 }
    651 
    652 TextDiagnostic::TextDiagnostic(raw_ostream &OS,
    653                                const LangOptions &LangOpts,
    654                                const DiagnosticOptions &DiagOpts)
    655   : DiagnosticRenderer(LangOpts, DiagOpts), OS(OS) {}
    656 
    657 TextDiagnostic::~TextDiagnostic() {}
    658 
    659 void
    660 TextDiagnostic::emitDiagnosticMessage(SourceLocation Loc,
    661                                       PresumedLoc PLoc,
    662                                       DiagnosticsEngine::Level Level,
    663                                       StringRef Message,
    664                                       ArrayRef<clang::CharSourceRange> Ranges,
    665                                       const SourceManager *SM,
    666                                       DiagOrStoredDiag D) {
    667   uint64_t StartOfLocationInfo = OS.tell();
    668 
    669   // Emit the location of this particular diagnostic.
    670   if (Loc.isValid())
    671     emitDiagnosticLoc(Loc, PLoc, Level, Ranges, *SM);
    672 
    673   if (DiagOpts.ShowColors)
    674     OS.resetColor();
    675 
    676   printDiagnosticLevel(OS, Level, DiagOpts.ShowColors);
    677   printDiagnosticMessage(OS, Level, Message,
    678                          OS.tell() - StartOfLocationInfo,
    679                          DiagOpts.MessageLength, DiagOpts.ShowColors);
    680 }
    681 
    682 /*static*/ void
    683 TextDiagnostic::printDiagnosticLevel(raw_ostream &OS,
    684                                      DiagnosticsEngine::Level Level,
    685                                      bool ShowColors) {
    686   if (ShowColors) {
    687     // Print diagnostic category in bold and color
    688     switch (Level) {
    689     case DiagnosticsEngine::Ignored:
    690       llvm_unreachable("Invalid diagnostic type");
    691     case DiagnosticsEngine::Note:    OS.changeColor(noteColor, true); break;
    692     case DiagnosticsEngine::Warning: OS.changeColor(warningColor, true); break;
    693     case DiagnosticsEngine::Error:   OS.changeColor(errorColor, true); break;
    694     case DiagnosticsEngine::Fatal:   OS.changeColor(fatalColor, true); break;
    695     }
    696   }
    697 
    698   switch (Level) {
    699   case DiagnosticsEngine::Ignored:
    700     llvm_unreachable("Invalid diagnostic type");
    701   case DiagnosticsEngine::Note:    OS << "note: "; break;
    702   case DiagnosticsEngine::Warning: OS << "warning: "; break;
    703   case DiagnosticsEngine::Error:   OS << "error: "; break;
    704   case DiagnosticsEngine::Fatal:   OS << "fatal error: "; break;
    705   }
    706 
    707   if (ShowColors)
    708     OS.resetColor();
    709 }
    710 
    711 /*static*/ void
    712 TextDiagnostic::printDiagnosticMessage(raw_ostream &OS,
    713                                        DiagnosticsEngine::Level Level,
    714                                        StringRef Message,
    715                                        unsigned CurrentColumn, unsigned Columns,
    716                                        bool ShowColors) {
    717   bool Bold = false;
    718   if (ShowColors) {
    719     // Print warnings, errors and fatal errors in bold, no color
    720     switch (Level) {
    721     case DiagnosticsEngine::Warning:
    722     case DiagnosticsEngine::Error:
    723     case DiagnosticsEngine::Fatal:
    724       OS.changeColor(savedColor, true);
    725       Bold = true;
    726       break;
    727     default: break; //don't bold notes
    728     }
    729   }
    730 
    731   if (Columns)
    732     printWordWrapped(OS, Message, Columns, CurrentColumn, Bold);
    733   else {
    734     bool Normal = true;
    735     applyTemplateHighlighting(OS, Message, Normal, Bold);
    736     assert(Normal && "Formatting should have returned to normal");
    737   }
    738 
    739   if (ShowColors)
    740     OS.resetColor();
    741   OS << '\n';
    742 }
    743 
    744 /// \brief Print out the file/line/column information and include trace.
    745 ///
    746 /// This method handlen the emission of the diagnostic location information.
    747 /// This includes extracting as much location information as is present for
    748 /// the diagnostic and printing it, as well as any include stack or source
    749 /// ranges necessary.
    750 void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
    751                                        DiagnosticsEngine::Level Level,
    752                                        ArrayRef<CharSourceRange> Ranges,
    753                                        const SourceManager &SM) {
    754   if (PLoc.isInvalid()) {
    755     // At least print the file name if available:
    756     FileID FID = SM.getFileID(Loc);
    757     if (!FID.isInvalid()) {
    758       const FileEntry* FE = SM.getFileEntryForID(FID);
    759       if (FE && FE->getName()) {
    760         OS << FE->getName();
    761         if (FE->getDevice() == 0 && FE->getInode() == 0
    762             && FE->getFileMode() == 0) {
    763           // in PCH is a guess, but a good one:
    764           OS << " (in PCH)";
    765         }
    766         OS << ": ";
    767       }
    768     }
    769     return;
    770   }
    771   unsigned LineNo = PLoc.getLine();
    772 
    773   if (!DiagOpts.ShowLocation)
    774     return;
    775 
    776   if (DiagOpts.ShowColors)
    777     OS.changeColor(savedColor, true);
    778 
    779   OS << PLoc.getFilename();
    780   switch (DiagOpts.Format) {
    781   case DiagnosticOptions::Clang: OS << ':'  << LineNo; break;
    782   case DiagnosticOptions::Msvc:  OS << '('  << LineNo; break;
    783   case DiagnosticOptions::Vi:    OS << " +" << LineNo; break;
    784   }
    785 
    786   if (DiagOpts.ShowColumn)
    787     // Compute the column number.
    788     if (unsigned ColNo = PLoc.getColumn()) {
    789       if (DiagOpts.Format == DiagnosticOptions::Msvc) {
    790         OS << ',';
    791         ColNo--;
    792       } else
    793         OS << ':';
    794       OS << ColNo;
    795     }
    796   switch (DiagOpts.Format) {
    797   case DiagnosticOptions::Clang:
    798   case DiagnosticOptions::Vi:    OS << ':';    break;
    799   case DiagnosticOptions::Msvc:  OS << ") : "; break;
    800   }
    801 
    802   if (DiagOpts.ShowSourceRanges && !Ranges.empty()) {
    803     FileID CaretFileID =
    804       SM.getFileID(SM.getExpansionLoc(Loc));
    805     bool PrintedRange = false;
    806 
    807     for (ArrayRef<CharSourceRange>::const_iterator RI = Ranges.begin(),
    808          RE = Ranges.end();
    809          RI != RE; ++RI) {
    810       // Ignore invalid ranges.
    811       if (!RI->isValid()) continue;
    812 
    813       SourceLocation B = SM.getExpansionLoc(RI->getBegin());
    814       SourceLocation E = SM.getExpansionLoc(RI->getEnd());
    815 
    816       // If the End location and the start location are the same and are a
    817       // macro location, then the range was something that came from a
    818       // macro expansion or _Pragma.  If this is an object-like macro, the
    819       // best we can do is to highlight the range.  If this is a
    820       // function-like macro, we'd also like to highlight the arguments.
    821       if (B == E && RI->getEnd().isMacroID())
    822         E = SM.getExpansionRange(RI->getEnd()).second;
    823 
    824       std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
    825       std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
    826 
    827       // If the start or end of the range is in another file, just discard
    828       // it.
    829       if (BInfo.first != CaretFileID || EInfo.first != CaretFileID)
    830         continue;
    831 
    832       // Add in the length of the token, so that we cover multi-char
    833       // tokens.
    834       unsigned TokSize = 0;
    835       if (RI->isTokenRange())
    836         TokSize = Lexer::MeasureTokenLength(E, SM, LangOpts);
    837 
    838       OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':'
    839         << SM.getColumnNumber(BInfo.first, BInfo.second) << '-'
    840         << SM.getLineNumber(EInfo.first, EInfo.second) << ':'
    841         << (SM.getColumnNumber(EInfo.first, EInfo.second)+TokSize)
    842         << '}';
    843       PrintedRange = true;
    844     }
    845 
    846     if (PrintedRange)
    847       OS << ':';
    848   }
    849   OS << ' ';
    850 }
    851 
    852 void TextDiagnostic::emitBasicNote(StringRef Message) {
    853   // FIXME: Emit this as a real note diagnostic.
    854   // FIXME: Format an actual diagnostic rather than a hard coded string.
    855   OS << "note: " << Message << "\n";
    856 }
    857 
    858 void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
    859                                          PresumedLoc PLoc,
    860                                          const SourceManager &SM) {
    861   if (DiagOpts.ShowLocation)
    862     OS << "In file included from " << PLoc.getFilename() << ':'
    863        << PLoc.getLine() << ":\n";
    864   else
    865     OS << "In included file:\n";
    866 }
    867 
    868 /// \brief Emit a code snippet and caret line.
    869 ///
    870 /// This routine emits a single line's code snippet and caret line..
    871 ///
    872 /// \param Loc The location for the caret.
    873 /// \param Ranges The underlined ranges for this code snippet.
    874 /// \param Hints The FixIt hints active for this diagnostic.
    875 void TextDiagnostic::emitSnippetAndCaret(
    876     SourceLocation Loc, DiagnosticsEngine::Level Level,
    877     SmallVectorImpl<CharSourceRange>& Ranges,
    878     ArrayRef<FixItHint> Hints,
    879     const SourceManager &SM) {
    880   assert(!Loc.isInvalid() && "must have a valid source location here");
    881   assert(Loc.isFileID() && "must have a file location here");
    882 
    883   // If caret diagnostics are enabled and we have location, we want to
    884   // emit the caret.  However, we only do this if the location moved
    885   // from the last diagnostic, if the last diagnostic was a note that
    886   // was part of a different warning or error diagnostic, or if the
    887   // diagnostic has ranges.  We don't want to emit the same caret
    888   // multiple times if one loc has multiple diagnostics.
    889   if (!DiagOpts.ShowCarets)
    890     return;
    891   if (Loc == LastLoc && Ranges.empty() && Hints.empty() &&
    892       (LastLevel != DiagnosticsEngine::Note || Level == LastLevel))
    893     return;
    894 
    895   // Decompose the location into a FID/Offset pair.
    896   std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
    897   FileID FID = LocInfo.first;
    898   unsigned FileOffset = LocInfo.second;
    899 
    900   // Get information about the buffer it points into.
    901   bool Invalid = false;
    902   const char *BufStart = SM.getBufferData(FID, &Invalid).data();
    903   if (Invalid)
    904     return;
    905 
    906   unsigned LineNo = SM.getLineNumber(FID, FileOffset);
    907   unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
    908 
    909   // Rewind from the current position to the start of the line.
    910   const char *TokPtr = BufStart+FileOffset;
    911   const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based.
    912 
    913 
    914   // Compute the line end.  Scan forward from the error position to the end of
    915   // the line.
    916   const char *LineEnd = TokPtr;
    917   while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')
    918     ++LineEnd;
    919 
    920   // Copy the line of code into an std::string for ease of manipulation.
    921   std::string SourceLine(LineStart, LineEnd);
    922 
    923   // Create a line for the caret that is filled with spaces that is the same
    924   // length as the line of source code.
    925   std::string CaretLine(LineEnd-LineStart, ' ');
    926 
    927   const SourceColumnMap sourceColMap(SourceLine, DiagOpts.TabStop);
    928 
    929   // Highlight all of the characters covered by Ranges with ~ characters.
    930   for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
    931                                                   E = Ranges.end();
    932        I != E; ++I)
    933     highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM);
    934 
    935   // Next, insert the caret itself.
    936   ColNo = sourceColMap.byteToColumn(ColNo-1);
    937   if (CaretLine.size()<ColNo+1)
    938     CaretLine.resize(ColNo+1, ' ');
    939   CaretLine[ColNo] = '^';
    940 
    941   std::string FixItInsertionLine = buildFixItInsertionLine(LineNo,
    942                                                            sourceColMap,
    943                                                            Hints, SM);
    944 
    945   // If the source line is too long for our terminal, select only the
    946   // "interesting" source region within that line.
    947   unsigned Columns = DiagOpts.MessageLength;
    948   if (Columns)
    949     selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine,
    950                                   Columns, sourceColMap);
    951 
    952   // If we are in -fdiagnostics-print-source-range-info mode, we are trying
    953   // to produce easily machine parsable output.  Add a space before the
    954   // source line and the caret to make it trivial to tell the main diagnostic
    955   // line from what the user is intended to see.
    956   if (DiagOpts.ShowSourceRanges) {
    957     SourceLine = ' ' + SourceLine;
    958     CaretLine = ' ' + CaretLine;
    959   }
    960 
    961   // Finally, remove any blank spaces from the end of CaretLine.
    962   while (CaretLine[CaretLine.size()-1] == ' ')
    963     CaretLine.erase(CaretLine.end()-1);
    964 
    965   // Emit what we have computed.
    966   emitSnippet(SourceLine);
    967 
    968   if (DiagOpts.ShowColors)
    969     OS.changeColor(caretColor, true);
    970   OS << CaretLine << '\n';
    971   if (DiagOpts.ShowColors)
    972     OS.resetColor();
    973 
    974   if (!FixItInsertionLine.empty()) {
    975     if (DiagOpts.ShowColors)
    976       // Print fixit line in color
    977       OS.changeColor(fixitColor, false);
    978     if (DiagOpts.ShowSourceRanges)
    979       OS << ' ';
    980     OS << FixItInsertionLine << '\n';
    981     if (DiagOpts.ShowColors)
    982       OS.resetColor();
    983   }
    984 
    985   // Print out any parseable fixit information requested by the options.
    986   emitParseableFixits(Hints, SM);
    987 }
    988 
    989 void TextDiagnostic::emitSnippet(StringRef line) {
    990   if (line.empty())
    991     return;
    992 
    993   size_t i = 0;
    994 
    995   std::string to_print;
    996   bool print_reversed = false;
    997 
    998   while (i<line.size()) {
    999     std::pair<SmallString<16>,bool> res
   1000         = printableTextForNextCharacter(line, &i, DiagOpts.TabStop);
   1001     bool was_printable = res.second;
   1002 
   1003     if (DiagOpts.ShowColors && was_printable == print_reversed) {
   1004       if (print_reversed)
   1005         OS.reverseColor();
   1006       OS << to_print;
   1007       to_print.clear();
   1008       if (DiagOpts.ShowColors)
   1009         OS.resetColor();
   1010     }
   1011 
   1012     print_reversed = !was_printable;
   1013     to_print += res.first.str();
   1014   }
   1015 
   1016   if (print_reversed && DiagOpts.ShowColors)
   1017     OS.reverseColor();
   1018   OS << to_print;
   1019   if (print_reversed && DiagOpts.ShowColors)
   1020     OS.resetColor();
   1021 
   1022   OS << '\n';
   1023 }
   1024 
   1025 /// \brief Highlight a SourceRange (with ~'s) for any characters on LineNo.
   1026 void TextDiagnostic::highlightRange(const CharSourceRange &R,
   1027                                     unsigned LineNo, FileID FID,
   1028                                     const SourceColumnMap &map,
   1029                                     std::string &CaretLine,
   1030                                     const SourceManager &SM) {
   1031   if (!R.isValid()) return;
   1032 
   1033   SourceLocation Begin = SM.getExpansionLoc(R.getBegin());
   1034   SourceLocation End = SM.getExpansionLoc(R.getEnd());
   1035 
   1036   // If the End location and the start location are the same and are a macro
   1037   // location, then the range was something that came from a macro expansion
   1038   // or _Pragma.  If this is an object-like macro, the best we can do is to
   1039   // highlight the range.  If this is a function-like macro, we'd also like to
   1040   // highlight the arguments.
   1041   if (Begin == End && R.getEnd().isMacroID())
   1042     End = SM.getExpansionRange(R.getEnd()).second;
   1043 
   1044   unsigned StartLineNo = SM.getExpansionLineNumber(Begin);
   1045   if (StartLineNo > LineNo || SM.getFileID(Begin) != FID)
   1046     return;  // No intersection.
   1047 
   1048   unsigned EndLineNo = SM.getExpansionLineNumber(End);
   1049   if (EndLineNo < LineNo || SM.getFileID(End) != FID)
   1050     return;  // No intersection.
   1051 
   1052   // Compute the column number of the start.
   1053   unsigned StartColNo = 0;
   1054   if (StartLineNo == LineNo) {
   1055     StartColNo = SM.getExpansionColumnNumber(Begin);
   1056     if (StartColNo) --StartColNo;  // Zero base the col #.
   1057   }
   1058 
   1059   // Compute the column number of the end.
   1060   unsigned EndColNo = map.getSourceLine().size();
   1061   if (EndLineNo == LineNo) {
   1062     EndColNo = SM.getExpansionColumnNumber(End);
   1063     if (EndColNo) {
   1064       --EndColNo;  // Zero base the col #.
   1065 
   1066       // Add in the length of the token, so that we cover multi-char tokens if
   1067       // this is a token range.
   1068       if (R.isTokenRange())
   1069         EndColNo += Lexer::MeasureTokenLength(End, SM, LangOpts);
   1070     } else {
   1071       EndColNo = CaretLine.size();
   1072     }
   1073   }
   1074 
   1075   assert(StartColNo <= EndColNo && "Invalid range!");
   1076 
   1077   // Check that a token range does not highlight only whitespace.
   1078   if (R.isTokenRange()) {
   1079     // Pick the first non-whitespace column.
   1080     while (StartColNo < map.getSourceLine().size() &&
   1081            (map.getSourceLine()[StartColNo] == ' ' ||
   1082             map.getSourceLine()[StartColNo] == '\t'))
   1083       ++StartColNo;
   1084 
   1085     // Pick the last non-whitespace column.
   1086     if (EndColNo > map.getSourceLine().size())
   1087       EndColNo = map.getSourceLine().size();
   1088     while (EndColNo-1 &&
   1089            (map.getSourceLine()[EndColNo-1] == ' ' ||
   1090             map.getSourceLine()[EndColNo-1] == '\t'))
   1091       --EndColNo;
   1092 
   1093     // If the start/end passed each other, then we are trying to highlight a
   1094     // range that just exists in whitespace, which must be some sort of other
   1095     // bug.
   1096     assert(StartColNo <= EndColNo && "Trying to highlight whitespace??");
   1097   }
   1098 
   1099   assert(StartColNo <= map.getSourceLine().size() && "Invalid range!");
   1100   assert(EndColNo <= map.getSourceLine().size() && "Invalid range!");
   1101 
   1102   // Fill the range with ~'s.
   1103   StartColNo = map.byteToColumn(StartColNo);
   1104   EndColNo = map.byteToColumn(EndColNo);
   1105 
   1106   assert(StartColNo <= EndColNo && "Invalid range!");
   1107   if (CaretLine.size() < EndColNo)
   1108     CaretLine.resize(EndColNo,' ');
   1109   std::fill(CaretLine.begin()+StartColNo,CaretLine.begin()+EndColNo,'~');
   1110 }
   1111 
   1112 std::string TextDiagnostic::buildFixItInsertionLine(
   1113   unsigned LineNo,
   1114   const SourceColumnMap &map,
   1115   ArrayRef<FixItHint> Hints,
   1116   const SourceManager &SM) {
   1117 
   1118   std::string FixItInsertionLine;
   1119   if (Hints.empty() || !DiagOpts.ShowFixits)
   1120     return FixItInsertionLine;
   1121   unsigned PrevHintEndCol = 0;
   1122 
   1123   for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
   1124        I != E; ++I) {
   1125     if (!I->CodeToInsert.empty()) {
   1126       // We have an insertion hint. Determine whether the inserted
   1127       // code contains no newlines and is on the same line as the caret.
   1128       std::pair<FileID, unsigned> HintLocInfo
   1129         = SM.getDecomposedExpansionLoc(I->RemoveRange.getBegin());
   1130       if (LineNo == SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) &&
   1131           StringRef(I->CodeToInsert).find_first_of("\n\r") == StringRef::npos) {
   1132         // Insert the new code into the line just below the code
   1133         // that the user wrote.
   1134         // Note: When modifying this function, be very careful about what is a
   1135         // "column" (printed width, platform-dependent) and what is a
   1136         // "byte offset" (SourceManager "column").
   1137         unsigned HintByteOffset
   1138           = SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second) - 1;
   1139 
   1140         // The hint must start inside the source or right at the end
   1141         assert(HintByteOffset < static_cast<unsigned>(map.bytes())+1);
   1142         unsigned HintCol = map.byteToColumn(HintByteOffset);
   1143 
   1144         // If we inserted a long previous hint, push this one forwards, and add
   1145         // an extra space to show that this is not part of the previous
   1146         // completion. This is sort of the best we can do when two hints appear
   1147         // to overlap.
   1148         //
   1149         // Note that if this hint is located immediately after the previous
   1150         // hint, no space will be added, since the location is more important.
   1151         if (HintCol < PrevHintEndCol)
   1152           HintCol = PrevHintEndCol + 1;
   1153 
   1154         // FIXME: This function handles multibyte characters in the source, but
   1155         // not in the fixits. This assertion is intended to catch unintended
   1156         // use of multibyte characters in fixits. If we decide to do this, we'll
   1157         // have to track separate byte widths for the source and fixit lines.
   1158         assert((size_t)llvm::sys::locale::columnWidth(I->CodeToInsert) ==
   1159                I->CodeToInsert.size());
   1160 
   1161         // This relies on one byte per column in our fixit hints.
   1162         // This should NOT use HintByteOffset, because the source might have
   1163         // Unicode characters in earlier columns.
   1164         unsigned LastColumnModified = HintCol + I->CodeToInsert.size();
   1165         if (LastColumnModified > FixItInsertionLine.size())
   1166           FixItInsertionLine.resize(LastColumnModified, ' ');
   1167 
   1168         std::copy(I->CodeToInsert.begin(), I->CodeToInsert.end(),
   1169                   FixItInsertionLine.begin() + HintCol);
   1170 
   1171         PrevHintEndCol = LastColumnModified;
   1172       } else {
   1173         FixItInsertionLine.clear();
   1174         break;
   1175       }
   1176     }
   1177   }
   1178 
   1179   expandTabs(FixItInsertionLine, DiagOpts.TabStop);
   1180 
   1181   return FixItInsertionLine;
   1182 }
   1183 
   1184 void TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints,
   1185                                          const SourceManager &SM) {
   1186   if (!DiagOpts.ShowParseableFixits)
   1187     return;
   1188 
   1189   // We follow FixItRewriter's example in not (yet) handling
   1190   // fix-its in macros.
   1191   for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
   1192        I != E; ++I) {
   1193     if (I->RemoveRange.isInvalid() ||
   1194         I->RemoveRange.getBegin().isMacroID() ||
   1195         I->RemoveRange.getEnd().isMacroID())
   1196       return;
   1197   }
   1198 
   1199   for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
   1200        I != E; ++I) {
   1201     SourceLocation BLoc = I->RemoveRange.getBegin();
   1202     SourceLocation ELoc = I->RemoveRange.getEnd();
   1203 
   1204     std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc);
   1205     std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc);
   1206 
   1207     // Adjust for token ranges.
   1208     if (I->RemoveRange.isTokenRange())
   1209       EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, LangOpts);
   1210 
   1211     // We specifically do not do word-wrapping or tab-expansion here,
   1212     // because this is supposed to be easy to parse.
   1213     PresumedLoc PLoc = SM.getPresumedLoc(BLoc);
   1214     if (PLoc.isInvalid())
   1215       break;
   1216 
   1217     OS << "fix-it:\"";
   1218     OS.write_escaped(PLoc.getFilename());
   1219     OS << "\":{" << SM.getLineNumber(BInfo.first, BInfo.second)
   1220       << ':' << SM.getColumnNumber(BInfo.first, BInfo.second)
   1221       << '-' << SM.getLineNumber(EInfo.first, EInfo.second)
   1222       << ':' << SM.getColumnNumber(EInfo.first, EInfo.second)
   1223       << "}:\"";
   1224     OS.write_escaped(I->CodeToInsert);
   1225     OS << "\"\n";
   1226   }
   1227 }
   1228