TextDiagnostic.cpp revision 3f6f51e28231f65de9c2dd150a2d757b2162cfa3
1db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth//===--- TextDiagnostic.cpp - Text Diagnostic Pretty-Printing -------------===//
2db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth//
3db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth//                     The LLVM Compiler Infrastructure
4db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth//
5db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth// This file is distributed under the University of Illinois Open Source
6db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth// License. See LICENSE.TXT for details.
7db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth//
8db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth//===----------------------------------------------------------------------===//
9db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
10db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth#include "clang/Frontend/TextDiagnostic.h"
113f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose#include "clang/Basic/CharInfo.h"
1202c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor#include "clang/Basic/DiagnosticOptions.h"
1355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/FileManager.h"
1455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/SourceManager.h"
15db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth#include "clang/Lex/Lexer.h"
16db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth#include "llvm/ADT/SmallString.h"
176749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell#include "llvm/ADT/StringExtras.h"
18cb5620c9b213f4bd323912159fdddda35e258a14Dmitri Gribenko#include "llvm/Support/ConvertUTF.h"
1955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/ErrorHandling.h"
2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/Locale.h"
2155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/MemoryBuffer.h"
2255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/raw_ostream.h"
23db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth#include <algorithm>
246749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
25db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthusing namespace clang;
26db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
27db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic const enum raw_ostream::Colors noteColor =
28db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  raw_ostream::BLACK;
29db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic const enum raw_ostream::Colors fixitColor =
30db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  raw_ostream::GREEN;
31db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic const enum raw_ostream::Colors caretColor =
32db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  raw_ostream::GREEN;
33db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic const enum raw_ostream::Colors warningColor =
34db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  raw_ostream::MAGENTA;
35246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieustatic const enum raw_ostream::Colors templateColor =
36246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu  raw_ostream::CYAN;
37db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic const enum raw_ostream::Colors errorColor = raw_ostream::RED;
38db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic const enum raw_ostream::Colors fatalColor = raw_ostream::RED;
39db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth// Used for changing only the bold attribute.
40db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic const enum raw_ostream::Colors savedColor =
41db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  raw_ostream::SAVEDCOLOR;
42db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
43246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu/// \brief Add highlights to differences in template strings.
44246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieustatic void applyTemplateHighlighting(raw_ostream &OS, StringRef Str,
45b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu                                      bool &Normal, bool Bold) {
464ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer  while (1) {
474ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer    size_t Pos = Str.find(ToggleHighlight);
484ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer    OS << Str.slice(0, Pos);
494ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer    if (Pos == StringRef::npos)
504ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer      break;
514ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer
524ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer    Str = Str.substr(Pos + 1);
534ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer    if (Normal)
544ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer      OS.changeColor(templateColor, true);
554ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer    else {
564ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer      OS.resetColor();
574ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer      if (Bold)
584ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer        OS.changeColor(savedColor, true);
59246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu    }
604ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer    Normal = !Normal;
614ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer  }
62246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu}
63246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu
64db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief Number of spaces to indent when word-wrapping.
65db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthconst unsigned WordWrapIndentation = 6;
66db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
67d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramerstatic int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i) {
686749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  int bytes = 0;
696749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  while (0<i) {
706749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    if (SourceLine[--i]=='\t')
716749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      break;
726749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    ++bytes;
736749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
746749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  return bytes;
756749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell}
766749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
776749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// \brief returns a printable representation of first item from input range
786749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
796749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// This function returns a printable representation of the next item in a line
806749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  of source. If the next byte begins a valid and printable character, that
816749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  character is returned along with 'true'.
826749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
836749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// Otherwise, if the next byte begins a valid, but unprintable character, a
846749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  printable, escaped representation of the character is returned, along with
856749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  'false'. Otherwise a printable, escaped representation of the next byte
866749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  is returned along with 'false'.
876749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
886749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// \note The index is updated to be used with a subsequent call to
896749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///        printableTextForNextCharacter.
906749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
916749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// \param SourceLine The line of source
926749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// \param i Pointer to byte index,
936749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// \param TabStop used to expand tabs
94f3477c13eeaf11b32a41f181398fb5deffd0dd73Sylvestre Ledru/// \return pair(printable text, 'true' iff original text was printable)
956749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
96d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramerstatic std::pair<SmallString<16>, bool>
976749dd50869281f9b49ad5960e25288c15a71cacSeth CantrellprintableTextForNextCharacter(StringRef SourceLine, size_t *i,
986749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                              unsigned TabStop) {
996749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(i && "i must not be null");
1006749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(*i<SourceLine.size() && "must point to a valid index");
1016749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1026749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (SourceLine[*i]=='\t') {
1036749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop &&
1046749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell           "Invalid -ftabstop value");
1056749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    unsigned col = bytesSincePreviousTabOrLineBegin(SourceLine, *i);
1066749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    unsigned NumSpaces = TabStop - col%TabStop;
1076749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(0 < NumSpaces && NumSpaces <= TabStop
1086749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell           && "Invalid computation of space amt");
1096749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    ++(*i);
1106749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1116749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    SmallString<16> expandedTab;
1126749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    expandedTab.assign(NumSpaces, ' ');
1136749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return std::make_pair(expandedTab, true);
1146749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
1156749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1166749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned char const *begin, *end;
1176749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  begin = reinterpret_cast<unsigned char const *>(&*(SourceLine.begin() + *i));
118c6a2f6e2dd16368f4a60178b5e20b63fcafb5481Seth Cantrell  end = begin + (SourceLine.size() - *i);
1196749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1206749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (isLegalUTF8Sequence(begin, end)) {
1216749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    UTF32 c;
1226749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    UTF32 *cptr = &c;
1236749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    unsigned char const *original_begin = begin;
1240d1e645bbfd3727b0dd758bdb685c6e5c7592fecSeth Cantrell    unsigned char const *cp_end = begin+getNumBytesForUTF8(SourceLine[*i]);
1256749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1266749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    ConversionResult res = ConvertUTF8toUTF32(&begin, cp_end, &cptr, cptr+1,
1276749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                              strictConversion);
1280ddb097bb02ddee8f1924ee4fcca384cb18ad8c5Matt Beaumont-Gay    (void)res;
1296749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(conversionOK==res);
1306749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(0 < begin-original_begin
1316749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell           && "we must be further along in the string now");
1326749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    *i += begin-original_begin;
1336749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1346749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    if (!llvm::sys::locale::isPrint(c)) {
1356749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      // If next character is valid UTF-8, but not printable
1366749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      SmallString<16> expandedCP("<U+>");
1376749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      while (c) {
1386749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell        expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(c%16));
1396749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell        c/=16;
1406749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      }
1416749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      while (expandedCP.size() < 8)
1426749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell        expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(0));
1436749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      return std::make_pair(expandedCP, false);
1446749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    }
1456749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1466749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    // If next character is valid UTF-8, and printable
1476749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return std::make_pair(SmallString<16>(original_begin, cp_end), true);
1486749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1496749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
1506749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1516749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // If next byte is not valid UTF-8 (and therefore not printable)
1526749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  SmallString<16> expandedByte("<XX>");
1536749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned char byte = SourceLine[*i];
1546749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  expandedByte[1] = llvm::hexdigit(byte / 16);
1556749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  expandedByte[2] = llvm::hexdigit(byte % 16);
1566749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  ++(*i);
1576749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  return std::make_pair(expandedByte, false);
1586749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell}
1596749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
160d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramerstatic void expandTabs(std::string &SourceLine, unsigned TabStop) {
1616749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  size_t i = SourceLine.size();
1626749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  while (i>0) {
1636749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    i--;
1646749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    if (SourceLine[i]!='\t')
1656749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      continue;
1666749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    size_t tmp_i = i;
1676749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    std::pair<SmallString<16>,bool> res
1686749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      = printableTextForNextCharacter(SourceLine, &tmp_i, TabStop);
1696749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    SourceLine.replace(i, 1, res.first.c_str());
1706749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
1716749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell}
1726749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1736749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// This function takes a raw source line and produces a mapping from the bytes
1746749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  of the printable representation of the line to the columns those printable
1756749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  characters will appear at (numbering the first column as 0).
1766749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
1776749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// If a byte 'i' corresponds to muliple columns (e.g. the byte contains a tab
178bed28ac1d1463adca3ecf24fca5c30646fa9dbb2Sylvestre Ledru///  character) then the array will map that byte to the first column the
1796749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  tab appears at and the next value in the map will have been incremented
1806749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  more than once.
1816749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
1826749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// If a byte is the first in a sequence of bytes that together map to a single
1836749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  entity in the output, then the array will map that byte to the appropriate
1846749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  column while the subsequent bytes will be -1.
1856749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
1866749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// The last element in the array does not correspond to any byte in the input
1876749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  and instead is the number of columns needed to display the source
1886749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
1896749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// example: (given a tabstop of 8)
1906749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
1916749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///    "a \t \u3042" -> {0,1,2,8,9,-1,-1,11}
1926749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
1936b4f50662a1857d5203254fb2c52975e6f30fc90James Dennett///  (\\u3042 is represented in UTF-8 by three bytes and takes two columns to
1946749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///   display)
195d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramerstatic void byteToColumn(StringRef SourceLine, unsigned TabStop,
196d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramer                         SmallVectorImpl<int> &out) {
1976749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  out.clear();
1986749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1996749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (SourceLine.empty()) {
2006749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    out.resize(1u,0);
2016749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return;
2026749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
2036749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2046749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  out.resize(SourceLine.size()+1, -1);
2056749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2066749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  int columns = 0;
2076749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  size_t i = 0;
2086749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  while (i<SourceLine.size()) {
2096749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    out[i] = columns;
2106749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    std::pair<SmallString<16>,bool> res
2116749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      = printableTextForNextCharacter(SourceLine, &i, TabStop);
2126749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    columns += llvm::sys::locale::columnWidth(res.first);
2136749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
2146749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  out.back() = columns;
2156749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell}
2166749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2176749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// This function takes a raw source line and produces a mapping from columns
2186749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  to the byte of the source line that produced the character displaying at
2196749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  that column. This is the inverse of the mapping produced by byteToColumn()
2206749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
2216749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// The last element in the array is the number of bytes in the source string
2226749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
2236749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// example: (given a tabstop of 8)
2246749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
2256749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///    "a \t \u3042" -> {0,1,2,-1,-1,-1,-1,-1,3,4,-1,7}
2266749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
2276b4f50662a1857d5203254fb2c52975e6f30fc90James Dennett///  (\\u3042 is represented in UTF-8 by three bytes and takes two columns to
2286749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///   display)
229d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramerstatic void columnToByte(StringRef SourceLine, unsigned TabStop,
2306749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                         SmallVectorImpl<int> &out) {
2316749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  out.clear();
2326749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2336749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (SourceLine.empty()) {
2346749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    out.resize(1u, 0);
2356749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return;
2366749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
2376749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2386749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  int columns = 0;
2396749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  size_t i = 0;
2406749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  while (i<SourceLine.size()) {
2416749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    out.resize(columns+1, -1);
2426749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    out.back() = i;
2436749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    std::pair<SmallString<16>,bool> res
2446749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      = printableTextForNextCharacter(SourceLine, &i, TabStop);
2456749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    columns += llvm::sys::locale::columnWidth(res.first);
2466749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
2476749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  out.resize(columns+1, -1);
2486749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  out.back() = i;
2496749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell}
2506749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
251c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramernamespace {
2526749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrellstruct SourceColumnMap {
2536749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  SourceColumnMap(StringRef SourceLine, unsigned TabStop)
2546749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  : m_SourceLine(SourceLine) {
2556749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2566749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    ::byteToColumn(SourceLine, TabStop, m_byteToColumn);
2576749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    ::columnToByte(SourceLine, TabStop, m_columnToByte);
2586749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2596749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(m_byteToColumn.size()==SourceLine.size()+1);
2606749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(0 < m_byteToColumn.size() && 0 < m_columnToByte.size());
2616749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(m_byteToColumn.size()
2626749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell           == static_cast<unsigned>(m_columnToByte.back()+1));
2636749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(static_cast<unsigned>(m_byteToColumn.back()+1)
2646749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell           == m_columnToByte.size());
2656749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
2666749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  int columns() const { return m_byteToColumn.back(); }
2676749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  int bytes() const { return m_columnToByte.back(); }
268c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith
269c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith  /// \brief Map a byte to the column which it is at the start of, or return -1
270c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith  /// if it is not at the start of a column (for a UTF-8 trailing byte).
2716749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  int byteToColumn(int n) const {
2726749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(0<=n && n<static_cast<int>(m_byteToColumn.size()));
2736749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return m_byteToColumn[n];
2746749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
275c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith
276c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith  /// \brief Map a byte to the first column which contains it.
277c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith  int byteToContainingColumn(int N) const {
278c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith    assert(0 <= N && N < static_cast<int>(m_byteToColumn.size()));
279c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith    while (m_byteToColumn[N] == -1)
280c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith      --N;
281c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith    return m_byteToColumn[N];
282c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith  }
283c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith
284c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith  /// \brief Map a column to the byte which starts the column, or return -1 if
285c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith  /// the column the second or subsequent column of an expanded tab or similar
286c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith  /// multi-column entity.
2876749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  int columnToByte(int n) const {
2886749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(0<=n && n<static_cast<int>(m_columnToByte.size()));
2896749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return m_columnToByte[n];
2906749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
291c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith
292c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith  /// \brief Map from a byte index to the next byte which starts a column.
293c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith  int startOfNextColumn(int N) const {
294c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith    assert(0 <= N && N < static_cast<int>(m_columnToByte.size() - 1));
295c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith    while (byteToColumn(++N) == -1) {}
296c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith    return N;
297c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith  }
298c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith
299c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith  /// \brief Map from a byte index to the previous byte which starts a column.
300c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith  int startOfPreviousColumn(int N) const {
301c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith    assert(0 < N && N < static_cast<int>(m_columnToByte.size()));
302eaa5a2b5e099bf29856bc88b03cd7c9d473f671dSeth Cantrell    while (byteToColumn(--N) == -1) {}
303c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith    return N;
304c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith  }
305c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith
3066749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  StringRef getSourceLine() const {
3076749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return m_SourceLine;
3086749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
3096749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
3106749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrellprivate:
3116749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  const std::string m_SourceLine;
3126749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  SmallVector<int,200> m_byteToColumn;
3136749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  SmallVector<int,200> m_columnToByte;
3146749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell};
3156749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
3166749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell// used in assert in selectInterestingSourceRegion()
3176749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrellstruct char_out_of_range {
3186749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  const char lower,upper;
3196749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  char_out_of_range(char lower, char upper) :
3206749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    lower(lower), upper(upper) {}
3216749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  bool operator()(char c) { return c < lower || upper < c; }
3226749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell};
323c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer} // end anonymous namespace
3246749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
325db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief When the source code line we want to print is too long for
326db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// the terminal, select the "interesting" region.
3277531f571808201d44002fa38b67ee0a81e5ae936Chandler Carruthstatic void selectInterestingSourceRegion(std::string &SourceLine,
328db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                                          std::string &CaretLine,
329db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                                          std::string &FixItInsertionLine,
3306749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                          unsigned Columns,
3316749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                          const SourceColumnMap &map) {
3326749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned MaxColumns = std::max<unsigned>(map.columns(),
3336749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                           std::max(CaretLine.size(),
3346749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                                    FixItInsertionLine.size()));
3356749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // if the number of columns is less than the desired number we're done
3366749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (MaxColumns <= Columns)
3376749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return;
3386749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
3396749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // no special characters allowed in CaretLine or FixItInsertionLine
3406749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(CaretLine.end() ==
3416749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell         std::find_if(CaretLine.begin(), CaretLine.end(),
3426749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell         char_out_of_range(' ','~')));
3436749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(FixItInsertionLine.end() ==
3446749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell         std::find_if(FixItInsertionLine.begin(), FixItInsertionLine.end(),
3456749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell         char_out_of_range(' ','~')));
3466749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
347db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Find the slice that we need to display the full caret line
348db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // correctly.
349db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  unsigned CaretStart = 0, CaretEnd = CaretLine.size();
350db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  for (; CaretStart != CaretEnd; ++CaretStart)
3513f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose    if (!isWhitespace(CaretLine[CaretStart]))
352db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      break;
353db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
354db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  for (; CaretEnd != CaretStart; --CaretEnd)
3553f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose    if (!isWhitespace(CaretLine[CaretEnd - 1]))
356db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      break;
357db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
3586749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // caret has already been inserted into CaretLine so the above whitespace
3596749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // check is guaranteed to include the caret
360db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
361db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // If we have a fix-it line, make sure the slice includes all of the
362db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // fix-it information.
363db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (!FixItInsertionLine.empty()) {
364db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    unsigned FixItStart = 0, FixItEnd = FixItInsertionLine.size();
365db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    for (; FixItStart != FixItEnd; ++FixItStart)
3663f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose      if (!isWhitespace(FixItInsertionLine[FixItStart]))
367db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        break;
368db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
369db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    for (; FixItEnd != FixItStart; --FixItEnd)
3703f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose      if (!isWhitespace(FixItInsertionLine[FixItEnd - 1]))
371db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        break;
372db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
3736749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    CaretStart = std::min(FixItStart, CaretStart);
3746749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    CaretEnd = std::max(FixItEnd, CaretEnd);
375db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
376db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
377c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell  // CaretEnd may have been set at the middle of a character
378c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell  // If it's not at a character's first column then advance it past the current
379c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell  //   character.
380c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell  while (static_cast<int>(CaretEnd) < map.columns() &&
381c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell         -1 == map.columnToByte(CaretEnd))
382c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell    ++CaretEnd;
383c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell
384c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell  assert((static_cast<int>(CaretStart) > map.columns() ||
385c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell          -1!=map.columnToByte(CaretStart)) &&
386c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell         "CaretStart must not point to a column in the middle of a source"
387c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell         " line character");
388c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell  assert((static_cast<int>(CaretEnd) > map.columns() ||
389c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell          -1!=map.columnToByte(CaretEnd)) &&
390c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell         "CaretEnd must not point to a column in the middle of a source line"
391c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell         " character");
392c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell
393db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // CaretLine[CaretStart, CaretEnd) contains all of the interesting
394db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // parts of the caret line. While this slice is smaller than the
395db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // number of columns we have, try to grow the slice to encompass
396db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // more context.
397db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
3986749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned SourceStart = map.columnToByte(std::min<unsigned>(CaretStart,
3996749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                                             map.columns()));
4006749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned SourceEnd = map.columnToByte(std::min<unsigned>(CaretEnd,
4016749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                                           map.columns()));
4026749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
4036749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned CaretColumnsOutsideSource = CaretEnd-CaretStart
4046749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    - (map.byteToColumn(SourceEnd)-map.byteToColumn(SourceStart));
4056749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
4066749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  char const *front_ellipse = "  ...";
4076749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  char const *front_space   = "     ";
4086749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  char const *back_ellipse = "...";
4096749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned ellipses_space = strlen(front_ellipse) + strlen(back_ellipse);
410db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
411db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  unsigned TargetColumns = Columns;
4126749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // Give us extra room for the ellipses
4136749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  //  and any of the caret line that extends past the source
4146749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (TargetColumns > ellipses_space+CaretColumnsOutsideSource)
4156749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    TargetColumns -= ellipses_space+CaretColumnsOutsideSource;
4166749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
4176749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  while (SourceStart>0 || SourceEnd<SourceLine.size()) {
418db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    bool ExpandedRegion = false;
4196749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
4206749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    if (SourceStart>0) {
4219cffb4a9ae548245ede15850cb96dfedf56255feSeth Cantrell      unsigned NewStart = map.startOfPreviousColumn(SourceStart);
422db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
423db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // Skip over any whitespace we see here; we're looking for
424db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // another bit of interesting text.
425c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith      // FIXME: Detect non-ASCII whitespace characters too.
4263f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose      while (NewStart && isWhitespace(SourceLine[NewStart]))
427c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith        NewStart = map.startOfPreviousColumn(NewStart);
428db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
429db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // Skip over this bit of "interesting" text.
430c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith      while (NewStart) {
431c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith        unsigned Prev = map.startOfPreviousColumn(NewStart);
4323f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose        if (isWhitespace(SourceLine[Prev]))
433c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith          break;
434c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith        NewStart = Prev;
435c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith      }
436db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
437c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith      assert(map.byteToColumn(NewStart) != -1);
4386749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      unsigned NewColumns = map.byteToColumn(SourceEnd) -
4396749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                              map.byteToColumn(NewStart);
4406749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      if (NewColumns <= TargetColumns) {
4416749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell        SourceStart = NewStart;
442db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        ExpandedRegion = true;
443db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      }
444db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    }
445db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
4466749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    if (SourceEnd<SourceLine.size()) {
4479cffb4a9ae548245ede15850cb96dfedf56255feSeth Cantrell      unsigned NewEnd = map.startOfNextColumn(SourceEnd);
448db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
449db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // Skip over any whitespace we see here; we're looking for
450db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // another bit of interesting text.
451c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith      // FIXME: Detect non-ASCII whitespace characters too.
4523f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose      while (NewEnd < SourceLine.size() && isWhitespace(SourceLine[NewEnd]))
453c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith        NewEnd = map.startOfNextColumn(NewEnd);
454db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
455db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // Skip over this bit of "interesting" text.
4563f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose      while (NewEnd < SourceLine.size() && isWhitespace(SourceLine[NewEnd]))
457c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith        NewEnd = map.startOfNextColumn(NewEnd);
458db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
459c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith      assert(map.byteToColumn(NewEnd) != -1);
4606749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      unsigned NewColumns = map.byteToColumn(NewEnd) -
4616749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                              map.byteToColumn(SourceStart);
4626749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      if (NewColumns <= TargetColumns) {
4636749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell        SourceEnd = NewEnd;
464db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        ExpandedRegion = true;
465db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      }
466db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    }
467db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
468db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (!ExpandedRegion)
469db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      break;
470db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
471db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
4726749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  CaretStart = map.byteToColumn(SourceStart);
4736749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  CaretEnd = map.byteToColumn(SourceEnd) + CaretColumnsOutsideSource;
4746749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
475db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // [CaretStart, CaretEnd) is the slice we want. Update the various
476db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // output lines to show only this slice, with two-space padding
477db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // before the lines so that it looks nicer.
4786749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
4796749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(CaretStart!=(unsigned)-1 && CaretEnd!=(unsigned)-1 &&
4806749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell         SourceStart!=(unsigned)-1 && SourceEnd!=(unsigned)-1);
4816749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(SourceStart <= SourceEnd);
4826749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(CaretStart <= CaretEnd);
4836749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
4846749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned BackColumnsRemoved
4856749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    = map.byteToColumn(SourceLine.size())-map.byteToColumn(SourceEnd);
4866749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned FrontColumnsRemoved = CaretStart;
4876749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned ColumnsKept = CaretEnd-CaretStart;
4886749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
4896749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // We checked up front that the line needed truncation
4906749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(FrontColumnsRemoved+ColumnsKept+BackColumnsRemoved > Columns);
4916749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
4926749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // The line needs some trunctiona, and we'd prefer to keep the front
4936749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  //  if possible, so remove the back
494191db6dc0d6290b5f2993691e409ff2dc8b4345eSeth Cantrell  if (BackColumnsRemoved > strlen(back_ellipse))
4956749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    SourceLine.replace(SourceEnd, std::string::npos, back_ellipse);
4966749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
4976749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // If that's enough then we're done
4986749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (FrontColumnsRemoved+ColumnsKept <= Columns)
4996749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return;
5006749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
5016749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // Otherwise remove the front as well
502191db6dc0d6290b5f2993691e409ff2dc8b4345eSeth Cantrell  if (FrontColumnsRemoved > strlen(front_ellipse)) {
5036749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    SourceLine.replace(0, SourceStart, front_ellipse);
5046749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    CaretLine.replace(0, CaretStart, front_space);
5056749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    if (!FixItInsertionLine.empty())
5066749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      FixItInsertionLine.replace(0, CaretStart, front_space);
507db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
508db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
509db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
510db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief Skip over whitespace in the string, starting at the given
511db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// index.
512db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth///
513db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \returns The index of the first non-whitespace character that is
514db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// greater than or equal to Idx or, if no such character exists,
515db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// returns the end of the string.
516db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic unsigned skipWhitespace(unsigned Idx, StringRef Str, unsigned Length) {
5173f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose  while (Idx < Length && isWhitespace(Str[Idx]))
518db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    ++Idx;
519db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  return Idx;
520db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
521db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
522db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief If the given character is the start of some kind of
523db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// balanced punctuation (e.g., quotes or parentheses), return the
524db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// character that will terminate the punctuation.
525db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth///
526db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \returns The ending punctuation character, if any, or the NULL
527db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// character if the input character does not start any punctuation.
528db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic inline char findMatchingPunctuation(char c) {
529db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  switch (c) {
530db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  case '\'': return '\'';
531db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  case '`': return '\'';
532db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  case '"':  return '"';
533db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  case '(':  return ')';
534db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  case '[': return ']';
535db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  case '{': return '}';
536db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  default: break;
537db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
538db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
539db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  return 0;
540db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
541db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
542db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief Find the end of the word starting at the given offset
543db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// within a string.
544db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth///
545db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \returns the index pointing one character past the end of the
546db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// word.
547db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic unsigned findEndOfWord(unsigned Start, StringRef Str,
548db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                              unsigned Length, unsigned Column,
549db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                              unsigned Columns) {
550db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  assert(Start < Str.size() && "Invalid start position!");
551db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  unsigned End = Start + 1;
552db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
553db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // If we are already at the end of the string, take that as the word.
554db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (End == Str.size())
555db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    return End;
556db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
557db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Determine if the start of the string is actually opening
558db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // punctuation, e.g., a quote or parentheses.
559db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  char EndPunct = findMatchingPunctuation(Str[Start]);
560db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (!EndPunct) {
561db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // This is a normal word. Just find the first space character.
5623f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose    while (End < Length && !isWhitespace(Str[End]))
563db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      ++End;
564db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    return End;
565db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
566db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
567db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // We have the start of a balanced punctuation sequence (quotes,
568db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // parentheses, etc.). Determine the full sequence is.
569f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith  SmallString<16> PunctuationEndStack;
570db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  PunctuationEndStack.push_back(EndPunct);
571db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  while (End < Length && !PunctuationEndStack.empty()) {
572db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (Str[End] == PunctuationEndStack.back())
573db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      PunctuationEndStack.pop_back();
574db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    else if (char SubEndPunct = findMatchingPunctuation(Str[End]))
575db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      PunctuationEndStack.push_back(SubEndPunct);
576db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
577db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    ++End;
578db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
579db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
580db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Find the first space character after the punctuation ended.
5813f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose  while (End < Length && !isWhitespace(Str[End]))
582db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    ++End;
583db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
584db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  unsigned PunctWordLength = End - Start;
585db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (// If the word fits on this line
586db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      Column + PunctWordLength <= Columns ||
587db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // ... or the word is "short enough" to take up the next line
588db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // without too much ugly white space
589db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      PunctWordLength < Columns/3)
590db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    return End; // Take the whole thing as a single "word".
591db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
592db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // The whole quoted/parenthesized string is too long to print as a
593db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // single "word". Instead, find the "word" that starts just after
594db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // the punctuation and use that end-point instead. This will recurse
595db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // until it finds something small enough to consider a word.
596db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  return findEndOfWord(Start + 1, Str, Length, Column + 1, Columns);
597db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
598db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
599db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief Print the given string to a stream, word-wrapping it to
600db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// some number of columns in the process.
601db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth///
602db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param OS the stream to which the word-wrapping string will be
603db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// emitted.
604db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Str the string to word-wrap and output.
605db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Columns the number of columns to word-wrap to.
606db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Column the column number at which the first character of \p
607db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// Str will be printed. This will be non-zero when part of the first
608db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// line has already been printed.
609b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu/// \param Bold if the current text should be bold
610db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Indentation the number of spaces to indent any lines beyond
611db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// the first line.
612db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \returns true if word-wrapping was required, or false if the
613db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// string fit on the first line.
614db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic bool printWordWrapped(raw_ostream &OS, StringRef Str,
615db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                             unsigned Columns,
616db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                             unsigned Column = 0,
617b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu                             bool Bold = false,
618db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                             unsigned Indentation = WordWrapIndentation) {
619db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  const unsigned Length = std::min(Str.find('\n'), Str.size());
620246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu  bool TextNormal = true;
621db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
622db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // The string used to indent each line.
623f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith  SmallString<16> IndentStr;
624db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  IndentStr.assign(Indentation, ' ');
625db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  bool Wrapped = false;
626db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  for (unsigned WordStart = 0, WordEnd; WordStart < Length;
627db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth       WordStart = WordEnd) {
628db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // Find the beginning of the next word.
629db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    WordStart = skipWhitespace(WordStart, Str, Length);
630db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (WordStart == Length)
631db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      break;
632db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
633db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // Find the end of this word.
634db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    WordEnd = findEndOfWord(WordStart, Str, Length, Column, Columns);
635db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
636db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // Does this word fit on the current line?
637db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    unsigned WordLength = WordEnd - WordStart;
638db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (Column + WordLength < Columns) {
639db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // This word fits on the current line; print it there.
640db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      if (WordStart) {
641db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        OS << ' ';
642db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        Column += 1;
643db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      }
644246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu      applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength),
645b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu                                TextNormal, Bold);
646db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      Column += WordLength;
647db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      continue;
648db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    }
649db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
650db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // This word does not fit on the current line, so wrap to the next
651db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // line.
652db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS << '\n';
653db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS.write(&IndentStr[0], Indentation);
654246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu    applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength),
655b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu                              TextNormal, Bold);
656db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    Column = Indentation + WordLength;
657db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    Wrapped = true;
658db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
659db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
660db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Append any remaning text from the message with its existing formatting.
661b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu  applyTemplateHighlighting(OS, Str.substr(Length), TextNormal, Bold);
662246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu
663246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu  assert(TextNormal && "Text highlighted at end of diagnostic message.");
664db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
665db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  return Wrapped;
666db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
667db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
668db463bb2e4a9751f4cbe53996db751e1985ee966Chandler CarruthTextDiagnostic::TextDiagnostic(raw_ostream &OS,
669db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                               const LangOptions &LangOpts,
67002c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor                               DiagnosticOptions *DiagOpts)
67116afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  : DiagnosticRenderer(LangOpts, DiagOpts), OS(OS) {}
672db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
6732898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted KremenekTextDiagnostic::~TextDiagnostic() {}
674db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
6752898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid
6762898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted KremenekTextDiagnostic::emitDiagnosticMessage(SourceLocation Loc,
6772898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                      PresumedLoc PLoc,
6782898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                      DiagnosticsEngine::Level Level,
6792898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                      StringRef Message,
6802898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                      ArrayRef<clang::CharSourceRange> Ranges,
68116afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                      const SourceManager *SM,
6828be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek                                      DiagOrStoredDiag D) {
683db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  uint64_t StartOfLocationInfo = OS.tell();
684db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
6852898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  // Emit the location of this particular diagnostic.
68616afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  if (Loc.isValid())
68716afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis    emitDiagnosticLoc(Loc, PLoc, Level, Ranges, *SM);
6882898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
68902c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  if (DiagOpts->ShowColors)
690db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS.resetColor();
6912898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
69202c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  printDiagnosticLevel(OS, Level, DiagOpts->ShowColors);
693db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  printDiagnosticMessage(OS, Level, Message,
694db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                         OS.tell() - StartOfLocationInfo,
69502c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor                         DiagOpts->MessageLength, DiagOpts->ShowColors);
696db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
697db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
6986ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/*static*/ void
6996ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler CarruthTextDiagnostic::printDiagnosticLevel(raw_ostream &OS,
7006ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth                                     DiagnosticsEngine::Level Level,
7016ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth                                     bool ShowColors) {
7026ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  if (ShowColors) {
7036ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    // Print diagnostic category in bold and color
7046ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    switch (Level) {
7056ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    case DiagnosticsEngine::Ignored:
7066ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      llvm_unreachable("Invalid diagnostic type");
7076ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    case DiagnosticsEngine::Note:    OS.changeColor(noteColor, true); break;
7086ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    case DiagnosticsEngine::Warning: OS.changeColor(warningColor, true); break;
7096ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    case DiagnosticsEngine::Error:   OS.changeColor(errorColor, true); break;
7106ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    case DiagnosticsEngine::Fatal:   OS.changeColor(fatalColor, true); break;
7116ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    }
7126ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  }
7136ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
7146ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  switch (Level) {
7156ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticsEngine::Ignored:
7166ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    llvm_unreachable("Invalid diagnostic type");
7176ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticsEngine::Note:    OS << "note: "; break;
7186ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticsEngine::Warning: OS << "warning: "; break;
7196ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticsEngine::Error:   OS << "error: "; break;
7206ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticsEngine::Fatal:   OS << "fatal error: "; break;
7216ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  }
7226ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
7236ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  if (ShowColors)
7246ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    OS.resetColor();
7256ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth}
7266ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
7276ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/*static*/ void
7286ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler CarruthTextDiagnostic::printDiagnosticMessage(raw_ostream &OS,
7296ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth                                       DiagnosticsEngine::Level Level,
7306ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth                                       StringRef Message,
7316ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth                                       unsigned CurrentColumn, unsigned Columns,
7326ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth                                       bool ShowColors) {
733b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu  bool Bold = false;
7346ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  if (ShowColors) {
7356ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    // Print warnings, errors and fatal errors in bold, no color
7366ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    switch (Level) {
737b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu    case DiagnosticsEngine::Warning:
738b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu    case DiagnosticsEngine::Error:
739b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu    case DiagnosticsEngine::Fatal:
740b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu      OS.changeColor(savedColor, true);
741b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu      Bold = true;
742b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu      break;
7436ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    default: break; //don't bold notes
7446ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    }
7456ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  }
7466ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
7476ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  if (Columns)
748b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu    printWordWrapped(OS, Message, Columns, CurrentColumn, Bold);
74950badd523b9b90c0731423d002b13a00bf754036David Blaikie  else {
75050badd523b9b90c0731423d002b13a00bf754036David Blaikie    bool Normal = true;
751b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu    applyTemplateHighlighting(OS, Message, Normal, Bold);
75250badd523b9b90c0731423d002b13a00bf754036David Blaikie    assert(Normal && "Formatting should have returned to normal");
75350badd523b9b90c0731423d002b13a00bf754036David Blaikie  }
7546ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
7556ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  if (ShowColors)
7566ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    OS.resetColor();
7576ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  OS << '\n';
7586ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth}
7596ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
7606ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/// \brief Print out the file/line/column information and include trace.
7616ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth///
7626ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/// This method handlen the emission of the diagnostic location information.
7636ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/// This includes extracting as much location information as is present for
7646ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/// the diagnostic and printing it, as well as any include stack or source
7656ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/// ranges necessary.
7667531f571808201d44002fa38b67ee0a81e5ae936Chandler Carruthvoid TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
7676ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth                                       DiagnosticsEngine::Level Level,
76816afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                       ArrayRef<CharSourceRange> Ranges,
76916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                       const SourceManager &SM) {
7706ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  if (PLoc.isInvalid()) {
7716ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    // At least print the file name if available:
7726ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    FileID FID = SM.getFileID(Loc);
7736ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    if (!FID.isInvalid()) {
7746ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      const FileEntry* FE = SM.getFileEntryForID(FID);
7756ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      if (FE && FE->getName()) {
7766ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        OS << FE->getName();
7776ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        if (FE->getDevice() == 0 && FE->getInode() == 0
7786ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth            && FE->getFileMode() == 0) {
7796ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth          // in PCH is a guess, but a good one:
7806ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth          OS << " (in PCH)";
7816ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        }
7826ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        OS << ": ";
7836ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      }
7846ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    }
7856ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    return;
7866ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  }
7876ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  unsigned LineNo = PLoc.getLine();
7886ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
78902c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  if (!DiagOpts->ShowLocation)
7906ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    return;
7916ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
79202c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  if (DiagOpts->ShowColors)
7936ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    OS.changeColor(savedColor, true);
7946ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
7956ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  OS << PLoc.getFilename();
796dc7b641574a733624489bd87fc7061771edf2113Douglas Gregor  switch (DiagOpts->getFormat()) {
7976ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticOptions::Clang: OS << ':'  << LineNo; break;
7986ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticOptions::Msvc:  OS << '('  << LineNo; break;
7996ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticOptions::Vi:    OS << " +" << LineNo; break;
8006ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  }
8016ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
80202c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  if (DiagOpts->ShowColumn)
8036ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    // Compute the column number.
8046ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    if (unsigned ColNo = PLoc.getColumn()) {
805dc7b641574a733624489bd87fc7061771edf2113Douglas Gregor      if (DiagOpts->getFormat() == DiagnosticOptions::Msvc) {
8066ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        OS << ',';
8076ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        ColNo--;
8086ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      } else
8096ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        OS << ':';
8106ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      OS << ColNo;
8116ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    }
812dc7b641574a733624489bd87fc7061771edf2113Douglas Gregor  switch (DiagOpts->getFormat()) {
8136ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticOptions::Clang:
8146ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticOptions::Vi:    OS << ':';    break;
8156ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticOptions::Msvc:  OS << ") : "; break;
8166ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  }
8176ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
81802c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  if (DiagOpts->ShowSourceRanges && !Ranges.empty()) {
8196ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    FileID CaretFileID =
8206ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      SM.getFileID(SM.getExpansionLoc(Loc));
8216ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    bool PrintedRange = false;
8226ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8236ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    for (ArrayRef<CharSourceRange>::const_iterator RI = Ranges.begin(),
8246ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth         RE = Ranges.end();
8256ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth         RI != RE; ++RI) {
8266ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // Ignore invalid ranges.
8276ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      if (!RI->isValid()) continue;
8286ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8296ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      SourceLocation B = SM.getExpansionLoc(RI->getBegin());
8306ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      SourceLocation E = SM.getExpansionLoc(RI->getEnd());
8316ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8326ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // If the End location and the start location are the same and are a
8336ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // macro location, then the range was something that came from a
8346ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // macro expansion or _Pragma.  If this is an object-like macro, the
8356ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // best we can do is to highlight the range.  If this is a
8366ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // function-like macro, we'd also like to highlight the arguments.
8376ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      if (B == E && RI->getEnd().isMacroID())
8386ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        E = SM.getExpansionRange(RI->getEnd()).second;
8396ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8406ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
8416ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
8426ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8436ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // If the start or end of the range is in another file, just discard
8446ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // it.
8456ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      if (BInfo.first != CaretFileID || EInfo.first != CaretFileID)
8466ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        continue;
8476ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8486ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // Add in the length of the token, so that we cover multi-char
8496ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // tokens.
8506ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      unsigned TokSize = 0;
8516ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      if (RI->isTokenRange())
8526ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        TokSize = Lexer::MeasureTokenLength(E, SM, LangOpts);
8536ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8546ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':'
8556ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        << SM.getColumnNumber(BInfo.first, BInfo.second) << '-'
8566ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        << SM.getLineNumber(EInfo.first, EInfo.second) << ':'
8576ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        << (SM.getColumnNumber(EInfo.first, EInfo.second)+TokSize)
8586ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        << '}';
8596ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      PrintedRange = true;
8606ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    }
8616ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8626ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    if (PrintedRange)
8636ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      OS << ':';
8646ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  }
8656ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  OS << ' ';
8666ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth}
8676ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8682898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid TextDiagnostic::emitBasicNote(StringRef Message) {
8692898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  // FIXME: Emit this as a real note diagnostic.
8702898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  // FIXME: Format an actual diagnostic rather than a hard coded string.
8712898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  OS << "note: " << Message << "\n";
8722898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek}
873db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
8742898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
87516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                         PresumedLoc PLoc,
87616afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                         const SourceManager &SM) {
87702c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  if (DiagOpts->ShowLocation)
8782898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek    OS << "In file included from " << PLoc.getFilename() << ':'
8792898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek       << PLoc.getLine() << ":\n";
8802898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  else
8812898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek    OS << "In included file:\n";
882db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
883db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
8846c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregorvoid TextDiagnostic::emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
8856c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor                                        StringRef ModuleName,
8866c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor                                        const SourceManager &SM) {
8876c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor  if (DiagOpts->ShowLocation)
8886c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor    OS << "In module '" << ModuleName << "' imported from "
8896c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor       << PLoc.getFilename() << ':' << PLoc.getLine() << ":\n";
8906c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor  else
8916c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor    OS << "In module " << ModuleName << "':\n";
8926c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor}
8936c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor
894830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregorvoid TextDiagnostic::emitBuildingModuleLocation(SourceLocation Loc,
895830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor                                                PresumedLoc PLoc,
896830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor                                                StringRef ModuleName,
897830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor                                                const SourceManager &SM) {
898813bc7faa74bda8162db3dede57e07bfe764e86eDouglas Gregor  if (DiagOpts->ShowLocation && PLoc.getFilename())
899830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor    OS << "While building module '" << ModuleName << "' imported from "
900830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor      << PLoc.getFilename() << ':' << PLoc.getLine() << ":\n";
901830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor  else
902830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor    OS << "While building module '" << ModuleName << "':\n";
903830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor}
904830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor
905c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer/// \brief Highlight a SourceRange (with ~'s) for any characters on LineNo.
906c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramerstatic void highlightRange(const CharSourceRange &R,
907c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer                           unsigned LineNo, FileID FID,
908c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer                           const SourceColumnMap &map,
909c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer                           std::string &CaretLine,
910c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer                           const SourceManager &SM,
911c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer                           const LangOptions &LangOpts) {
912c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  if (!R.isValid()) return;
913c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
914c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  SourceLocation Begin = R.getBegin();
915c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  SourceLocation End = R.getEnd();
916c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
917c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  unsigned StartLineNo = SM.getExpansionLineNumber(Begin);
918c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  if (StartLineNo > LineNo || SM.getFileID(Begin) != FID)
919c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    return;  // No intersection.
920c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
921c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  unsigned EndLineNo = SM.getExpansionLineNumber(End);
922c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  if (EndLineNo < LineNo || SM.getFileID(End) != FID)
923c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    return;  // No intersection.
924c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
925c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  // Compute the column number of the start.
926c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  unsigned StartColNo = 0;
927c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  if (StartLineNo == LineNo) {
928c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    StartColNo = SM.getExpansionColumnNumber(Begin);
929c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    if (StartColNo) --StartColNo;  // Zero base the col #.
930c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  }
931c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
932c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  // Compute the column number of the end.
933c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  unsigned EndColNo = map.getSourceLine().size();
934c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  if (EndLineNo == LineNo) {
935c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    EndColNo = SM.getExpansionColumnNumber(End);
936c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    if (EndColNo) {
937c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer      --EndColNo;  // Zero base the col #.
938c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
939c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer      // Add in the length of the token, so that we cover multi-char tokens if
940c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer      // this is a token range.
941c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer      if (R.isTokenRange())
942c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        EndColNo += Lexer::MeasureTokenLength(End, SM, LangOpts);
943c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    } else {
944c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer      EndColNo = CaretLine.size();
945c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    }
946c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  }
947c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
948c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  assert(StartColNo <= EndColNo && "Invalid range!");
949c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
950c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  // Check that a token range does not highlight only whitespace.
951c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  if (R.isTokenRange()) {
952c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    // Pick the first non-whitespace column.
953c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    while (StartColNo < map.getSourceLine().size() &&
954c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer           (map.getSourceLine()[StartColNo] == ' ' ||
955c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer            map.getSourceLine()[StartColNo] == '\t'))
956c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer      StartColNo = map.startOfNextColumn(StartColNo);
957c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
958c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    // Pick the last non-whitespace column.
959c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    if (EndColNo > map.getSourceLine().size())
960c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer      EndColNo = map.getSourceLine().size();
961c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    while (EndColNo-1 &&
962c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer           (map.getSourceLine()[EndColNo-1] == ' ' ||
963c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer            map.getSourceLine()[EndColNo-1] == '\t'))
964c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer      EndColNo = map.startOfPreviousColumn(EndColNo);
965c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
966c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    // If the start/end passed each other, then we are trying to highlight a
967c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    // range that just exists in whitespace, which must be some sort of other
968c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    // bug.
969c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    assert(StartColNo <= EndColNo && "Trying to highlight whitespace??");
970c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  }
971c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
972c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  assert(StartColNo <= map.getSourceLine().size() && "Invalid range!");
973c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  assert(EndColNo <= map.getSourceLine().size() && "Invalid range!");
974c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
975c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  // Fill the range with ~'s.
976c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  StartColNo = map.byteToContainingColumn(StartColNo);
977c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  EndColNo = map.byteToContainingColumn(EndColNo);
978c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
979c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  assert(StartColNo <= EndColNo && "Invalid range!");
980c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  if (CaretLine.size() < EndColNo)
981c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    CaretLine.resize(EndColNo,' ');
982c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  std::fill(CaretLine.begin()+StartColNo,CaretLine.begin()+EndColNo,'~');
983c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer}
984c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
985c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramerstatic std::string buildFixItInsertionLine(unsigned LineNo,
986c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer                                           const SourceColumnMap &map,
987c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer                                           ArrayRef<FixItHint> Hints,
988c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer                                           const SourceManager &SM,
989c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer                                           const DiagnosticOptions *DiagOpts) {
990c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  std::string FixItInsertionLine;
991c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  if (Hints.empty() || !DiagOpts->ShowFixits)
992c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    return FixItInsertionLine;
993c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  unsigned PrevHintEndCol = 0;
994c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
995c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
996c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer       I != E; ++I) {
997c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    if (!I->CodeToInsert.empty()) {
998c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer      // We have an insertion hint. Determine whether the inserted
999c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer      // code contains no newlines and is on the same line as the caret.
1000c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer      std::pair<FileID, unsigned> HintLocInfo
1001c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        = SM.getDecomposedExpansionLoc(I->RemoveRange.getBegin());
1002c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer      if (LineNo == SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) &&
1003c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer          StringRef(I->CodeToInsert).find_first_of("\n\r") == StringRef::npos) {
1004c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // Insert the new code into the line just below the code
1005c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // that the user wrote.
1006c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // Note: When modifying this function, be very careful about what is a
1007c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // "column" (printed width, platform-dependent) and what is a
1008c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // "byte offset" (SourceManager "column").
1009c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        unsigned HintByteOffset
1010c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer          = SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second) - 1;
1011c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
1012c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // The hint must start inside the source or right at the end
1013c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        assert(HintByteOffset < static_cast<unsigned>(map.bytes())+1);
1014c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        unsigned HintCol = map.byteToContainingColumn(HintByteOffset);
1015c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
1016c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // If we inserted a long previous hint, push this one forwards, and add
1017c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // an extra space to show that this is not part of the previous
1018c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // completion. This is sort of the best we can do when two hints appear
1019c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // to overlap.
1020c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        //
1021c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // Note that if this hint is located immediately after the previous
1022c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // hint, no space will be added, since the location is more important.
1023c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        if (HintCol < PrevHintEndCol)
1024c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer          HintCol = PrevHintEndCol + 1;
1025c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
1026c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // FIXME: This function handles multibyte characters in the source, but
1027c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // not in the fixits. This assertion is intended to catch unintended
1028c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // use of multibyte characters in fixits. If we decide to do this, we'll
1029c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // have to track separate byte widths for the source and fixit lines.
1030c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        assert((size_t)llvm::sys::locale::columnWidth(I->CodeToInsert) ==
1031c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer               I->CodeToInsert.size());
1032c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
1033c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // This relies on one byte per column in our fixit hints.
1034c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // This should NOT use HintByteOffset, because the source might have
1035c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        // Unicode characters in earlier columns.
1036c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        unsigned LastColumnModified = HintCol + I->CodeToInsert.size();
1037c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        if (LastColumnModified > FixItInsertionLine.size())
1038c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer          FixItInsertionLine.resize(LastColumnModified, ' ');
1039c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
1040c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        std::copy(I->CodeToInsert.begin(), I->CodeToInsert.end(),
1041c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer                  FixItInsertionLine.begin() + HintCol);
1042c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
1043c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        PrevHintEndCol = LastColumnModified;
1044c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer      } else {
1045c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        FixItInsertionLine.clear();
1046c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer        break;
1047c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer      }
1048c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    }
1049c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  }
1050c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
1051c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  expandTabs(FixItInsertionLine, DiagOpts->TabStop);
1052c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
1053c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer  return FixItInsertionLine;
1054c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer}
1055c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer
1056db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief Emit a code snippet and caret line.
1057db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth///
1058db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// This routine emits a single line's code snippet and caret line..
1059db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth///
1060db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Loc The location for the caret.
1061db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Ranges The underlined ranges for this code snippet.
1062db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Hints The FixIt hints active for this diagnostic.
10637531f571808201d44002fa38b67ee0a81e5ae936Chandler Carruthvoid TextDiagnostic::emitSnippetAndCaret(
10644ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth    SourceLocation Loc, DiagnosticsEngine::Level Level,
1065db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    SmallVectorImpl<CharSourceRange>& Ranges,
106616afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis    ArrayRef<FixItHint> Hints,
106716afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis    const SourceManager &SM) {
1068db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  assert(!Loc.isInvalid() && "must have a valid source location here");
1069db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  assert(Loc.isFileID() && "must have a file location here");
1070db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
10714ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth  // If caret diagnostics are enabled and we have location, we want to
10724ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth  // emit the caret.  However, we only do this if the location moved
10734ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth  // from the last diagnostic, if the last diagnostic was a note that
10744ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth  // was part of a different warning or error diagnostic, or if the
10754ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth  // diagnostic has ranges.  We don't want to emit the same caret
10764ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth  // multiple times if one loc has multiple diagnostics.
107702c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  if (!DiagOpts->ShowCarets)
10784ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth    return;
10794ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth  if (Loc == LastLoc && Ranges.empty() && Hints.empty() &&
10804ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth      (LastLevel != DiagnosticsEngine::Note || Level == LastLevel))
10814ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth    return;
10824ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth
1083db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Decompose the location into a FID/Offset pair.
1084db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
1085db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  FileID FID = LocInfo.first;
1086db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  unsigned FileOffset = LocInfo.second;
1087db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1088db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Get information about the buffer it points into.
1089db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  bool Invalid = false;
109040d8e971a32a23856ce1ab0106ae75cf4b92ca9dNico Weber  const char *BufStart = SM.getBufferData(FID, &Invalid).data();
1091db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (Invalid)
1092db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    return;
1093db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1094db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  unsigned LineNo = SM.getLineNumber(FID, FileOffset);
1095db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
1096f6e74a35e0c0e53b2e65fc9fe86f8e4cadcca473Jordan Rose
1097f6e74a35e0c0e53b2e65fc9fe86f8e4cadcca473Jordan Rose  // Arbitrarily stop showing snippets when the line is too long.
109877163bc392be75795d58b1f6177a0a4626a57dcbNAKAMURA Takumi  static const ptrdiff_t MaxLineLengthToPrint = 4096;
109991165e74c8b480c1da3a719d764f4fa0e7b1b921Jordan Rose  if (ColNo > MaxLineLengthToPrint)
1100f6e74a35e0c0e53b2e65fc9fe86f8e4cadcca473Jordan Rose    return;
1101db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1102db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Rewind from the current position to the start of the line.
1103db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  const char *TokPtr = BufStart+FileOffset;
1104db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based.
1105db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1106db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Compute the line end.  Scan forward from the error position to the end of
1107db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // the line.
1108db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  const char *LineEnd = TokPtr;
110940d8e971a32a23856ce1ab0106ae75cf4b92ca9dNico Weber  while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')
1110db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    ++LineEnd;
1111db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1112f6e74a35e0c0e53b2e65fc9fe86f8e4cadcca473Jordan Rose  // Arbitrarily stop showing snippets when the line is too long.
111391165e74c8b480c1da3a719d764f4fa0e7b1b921Jordan Rose  if (LineEnd - LineStart > MaxLineLengthToPrint)
1114f6e74a35e0c0e53b2e65fc9fe86f8e4cadcca473Jordan Rose    return;
1115f6e74a35e0c0e53b2e65fc9fe86f8e4cadcca473Jordan Rose
1116db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Copy the line of code into an std::string for ease of manipulation.
1117db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  std::string SourceLine(LineStart, LineEnd);
1118db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1119db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Create a line for the caret that is filled with spaces that is the same
1120db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // length as the line of source code.
1121db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  std::string CaretLine(LineEnd-LineStart, ' ');
1122db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
112302c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  const SourceColumnMap sourceColMap(SourceLine, DiagOpts->TabStop);
11246749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1125db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Highlight all of the characters covered by Ranges with ~ characters.
1126db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
1127db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                                                  E = Ranges.end();
1128db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth       I != E; ++I)
1129c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer    highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM, LangOpts);
1130db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1131db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Next, insert the caret itself.
1132c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith  ColNo = sourceColMap.byteToContainingColumn(ColNo-1);
11336749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (CaretLine.size()<ColNo+1)
11346749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    CaretLine.resize(ColNo+1, ' ');
11356749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  CaretLine[ColNo] = '^';
1136e9a3b76ba589a8a884e978273beaed0d97cf9861Seth Cantrell
11376749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  std::string FixItInsertionLine = buildFixItInsertionLine(LineNo,
11386749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                                           sourceColMap,
1139c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer                                                           Hints, SM,
1140c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer                                                           DiagOpts.getPtr());
11416749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
11426749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // If the source line is too long for our terminal, select only the
11436749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // "interesting" source region within that line.
114402c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  unsigned Columns = DiagOpts->MessageLength;
11456749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (Columns)
11466749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine,
11476749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                  Columns, sourceColMap);
1148db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1149db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // If we are in -fdiagnostics-print-source-range-info mode, we are trying
1150db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // to produce easily machine parsable output.  Add a space before the
1151db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // source line and the caret to make it trivial to tell the main diagnostic
1152db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // line from what the user is intended to see.
115302c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  if (DiagOpts->ShowSourceRanges) {
1154db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    SourceLine = ' ' + SourceLine;
1155db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    CaretLine = ' ' + CaretLine;
1156db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
1157db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1158db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Finally, remove any blank spaces from the end of CaretLine.
1159db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  while (CaretLine[CaretLine.size()-1] == ' ')
1160db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    CaretLine.erase(CaretLine.end()-1);
1161db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1162db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Emit what we have computed.
11636749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  emitSnippet(SourceLine);
1164db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
116502c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  if (DiagOpts->ShowColors)
1166db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS.changeColor(caretColor, true);
1167db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  OS << CaretLine << '\n';
116802c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  if (DiagOpts->ShowColors)
1169db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS.resetColor();
1170db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1171db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (!FixItInsertionLine.empty()) {
117202c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor    if (DiagOpts->ShowColors)
1173db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // Print fixit line in color
1174db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      OS.changeColor(fixitColor, false);
117502c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor    if (DiagOpts->ShowSourceRanges)
1176db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      OS << ' ';
1177db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS << FixItInsertionLine << '\n';
117802c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor    if (DiagOpts->ShowColors)
1179db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      OS.resetColor();
1180db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
1181db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1182db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Print out any parseable fixit information requested by the options.
118316afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  emitParseableFixits(Hints, SM);
1184db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
1185db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1186d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramervoid TextDiagnostic::emitSnippet(StringRef line) {
11876749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (line.empty())
11886749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return;
11896749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
11906749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  size_t i = 0;
11916749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
11926749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  std::string to_print;
11936749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  bool print_reversed = false;
11946749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
11956749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  while (i<line.size()) {
11966749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    std::pair<SmallString<16>,bool> res
119702c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor        = printableTextForNextCharacter(line, &i, DiagOpts->TabStop);
11986749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    bool was_printable = res.second;
11996749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
120002c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor    if (DiagOpts->ShowColors && was_printable == print_reversed) {
12016749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      if (print_reversed)
12026749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell        OS.reverseColor();
12036749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      OS << to_print;
12046749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      to_print.clear();
120502c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor      if (DiagOpts->ShowColors)
12066749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell        OS.resetColor();
12076749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    }
12086749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
12096749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    print_reversed = !was_printable;
12106749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    to_print += res.first.str();
12116749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
12126749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
121302c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  if (print_reversed && DiagOpts->ShowColors)
12146749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    OS.reverseColor();
12156749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  OS << to_print;
121602c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  if (print_reversed && DiagOpts->ShowColors)
12176749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    OS.resetColor();
12186749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
12196749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  OS << '\n';
12206749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell}
12216749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
122216afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidisvoid TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints,
122316afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                         const SourceManager &SM) {
122402c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  if (!DiagOpts->ShowParseableFixits)
1225db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    return;
1226db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1227db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // We follow FixItRewriter's example in not (yet) handling
1228db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // fix-its in macros.
1229db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
1230db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth       I != E; ++I) {
1231db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (I->RemoveRange.isInvalid() ||
1232db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        I->RemoveRange.getBegin().isMacroID() ||
1233db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        I->RemoveRange.getEnd().isMacroID())
1234db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      return;
1235db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
1236db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1237db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
1238db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth       I != E; ++I) {
1239db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    SourceLocation BLoc = I->RemoveRange.getBegin();
1240db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    SourceLocation ELoc = I->RemoveRange.getEnd();
1241db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1242db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc);
1243db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc);
1244db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1245db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // Adjust for token ranges.
1246db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (I->RemoveRange.isTokenRange())
1247db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, LangOpts);
1248db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1249db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // We specifically do not do word-wrapping or tab-expansion here,
1250db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // because this is supposed to be easy to parse.
1251db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    PresumedLoc PLoc = SM.getPresumedLoc(BLoc);
1252db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (PLoc.isInvalid())
1253db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      break;
1254db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1255db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS << "fix-it:\"";
1256db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS.write_escaped(PLoc.getFilename());
1257db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS << "\":{" << SM.getLineNumber(BInfo.first, BInfo.second)
1258db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      << ':' << SM.getColumnNumber(BInfo.first, BInfo.second)
1259db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      << '-' << SM.getLineNumber(EInfo.first, EInfo.second)
1260db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      << ':' << SM.getColumnNumber(EInfo.first, EInfo.second)
1261db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      << "}:\"";
1262db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS.write_escaped(I->CodeToInsert);
1263db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS << "\"\n";
1264db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
1265db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
1266