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"
11db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth#include "clang/Basic/FileManager.h"
12db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth#include "clang/Basic/SourceManager.h"
136749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell#include "clang/Basic/ConvertUTF.h"
14db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth#include "clang/Frontend/DiagnosticOptions.h"
15db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth#include "clang/Lex/Lexer.h"
16db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth#include "llvm/Support/MemoryBuffer.h"
17db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth#include "llvm/Support/raw_ostream.h"
18db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth#include "llvm/Support/ErrorHandling.h"
196749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell#include "llvm/Support/Locale.h"
20db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth#include "llvm/ADT/SmallString.h"
216749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell#include "llvm/ADT/StringExtras.h"
22db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth#include <algorithm>
237094dee95f8c915d27097ac18b47d1ef31fd72edJoerg Sonnenberger#include <cctype>
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) {
46246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu  for (unsigned i = 0, e = Str.size(); i < e; ++i)
47246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu    if (Str[i] != ToggleHighlight) {
48246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu      OS << Str[i];
49246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu    } else {
50246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu      if (Normal)
51246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu        OS.changeColor(templateColor, true);
52b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu      else {
53246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu        OS.resetColor();
54b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu        if (Bold)
55b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu          OS.changeColor(savedColor, true);
56b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu      }
57246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu      Normal = !Normal;
58246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu    }
59246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu}
60246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu
61db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief Number of spaces to indent when word-wrapping.
62db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthconst unsigned WordWrapIndentation = 6;
63db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
64d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramerstatic int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i) {
656749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  int bytes = 0;
666749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  while (0<i) {
676749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    if (SourceLine[--i]=='\t')
686749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      break;
696749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    ++bytes;
706749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
716749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  return bytes;
726749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell}
736749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
746749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// \brief returns a printable representation of first item from input range
756749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
766749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// This function returns a printable representation of the next item in a line
776749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  of source. If the next byte begins a valid and printable character, that
786749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  character is returned along with 'true'.
796749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
806749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// Otherwise, if the next byte begins a valid, but unprintable character, a
816749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  printable, escaped representation of the character is returned, along with
826749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  'false'. Otherwise a printable, escaped representation of the next byte
836749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  is returned along with 'false'.
846749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
856749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// \note The index is updated to be used with a subsequent call to
866749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///        printableTextForNextCharacter.
876749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
886749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// \param SourceLine The line of source
896749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// \param i Pointer to byte index,
906749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// \param TabStop used to expand tabs
916749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// \return pair(printable text, 'true' iff original text was printable)
926749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
93d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramerstatic std::pair<SmallString<16>, bool>
946749dd50869281f9b49ad5960e25288c15a71cacSeth CantrellprintableTextForNextCharacter(StringRef SourceLine, size_t *i,
956749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                              unsigned TabStop) {
966749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(i && "i must not be null");
976749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(*i<SourceLine.size() && "must point to a valid index");
986749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
996749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (SourceLine[*i]=='\t') {
1006749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop &&
1016749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell           "Invalid -ftabstop value");
1026749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    unsigned col = bytesSincePreviousTabOrLineBegin(SourceLine, *i);
1036749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    unsigned NumSpaces = TabStop - col%TabStop;
1046749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(0 < NumSpaces && NumSpaces <= TabStop
1056749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell           && "Invalid computation of space amt");
1066749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    ++(*i);
1076749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1086749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    SmallString<16> expandedTab;
1096749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    expandedTab.assign(NumSpaces, ' ');
1106749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return std::make_pair(expandedTab, true);
1116749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
1126749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1136749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // FIXME: this data is copied from the private implementation of ConvertUTF.h
1146749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  static const char trailingBytesForUTF8[256] = {
1156749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1166749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1176749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1186749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1196749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1206749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1216749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1226749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
1236749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  };
1246749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1256749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned char const *begin, *end;
1266749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  begin = reinterpret_cast<unsigned char const *>(&*(SourceLine.begin() + *i));
1276749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  end = begin + SourceLine.size();
1286749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1296749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (isLegalUTF8Sequence(begin, end)) {
1306749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    UTF32 c;
1316749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    UTF32 *cptr = &c;
1326749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    unsigned char const *original_begin = begin;
1336749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    char trailingBytes = trailingBytesForUTF8[(unsigned char)SourceLine[*i]];
1346749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    unsigned char const *cp_end = begin+trailingBytes+1;
1356749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1366749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    ConversionResult res = ConvertUTF8toUTF32(&begin, cp_end, &cptr, cptr+1,
1376749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                              strictConversion);
1380ddb097bb02ddee8f1924ee4fcca384cb18ad8c5Matt Beaumont-Gay    (void)res;
1396749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(conversionOK==res);
1406749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(0 < begin-original_begin
1416749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell           && "we must be further along in the string now");
1426749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    *i += begin-original_begin;
1436749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1446749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    if (!llvm::sys::locale::isPrint(c)) {
1456749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      // If next character is valid UTF-8, but not printable
1466749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      SmallString<16> expandedCP("<U+>");
1476749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      while (c) {
1486749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell        expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(c%16));
1496749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell        c/=16;
1506749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      }
1516749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      while (expandedCP.size() < 8)
1526749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell        expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(0));
1536749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      return std::make_pair(expandedCP, false);
1546749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    }
1556749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1566749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    // If next character is valid UTF-8, and printable
1576749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return std::make_pair(SmallString<16>(original_begin, cp_end), true);
1586749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1596749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
1606749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1616749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // If next byte is not valid UTF-8 (and therefore not printable)
1626749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  SmallString<16> expandedByte("<XX>");
1636749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned char byte = SourceLine[*i];
1646749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  expandedByte[1] = llvm::hexdigit(byte / 16);
1656749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  expandedByte[2] = llvm::hexdigit(byte % 16);
1666749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  ++(*i);
1676749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  return std::make_pair(expandedByte, false);
1686749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell}
1696749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
170d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramerstatic void expandTabs(std::string &SourceLine, unsigned TabStop) {
1716749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  size_t i = SourceLine.size();
1726749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  while (i>0) {
1736749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    i--;
1746749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    if (SourceLine[i]!='\t')
1756749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      continue;
1766749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    size_t tmp_i = i;
1776749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    std::pair<SmallString<16>,bool> res
1786749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      = printableTextForNextCharacter(SourceLine, &tmp_i, TabStop);
1796749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    SourceLine.replace(i, 1, res.first.c_str());
1806749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
1816749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell}
1826749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1836749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// This function takes a raw source line and produces a mapping from the bytes
1846749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  of the printable representation of the line to the columns those printable
1856749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  characters will appear at (numbering the first column as 0).
1866749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
1876749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// If a byte 'i' corresponds to muliple columns (e.g. the byte contains a tab
188bed28ac1d1463adca3ecf24fca5c30646fa9dbb2Sylvestre Ledru///  character) then the array will map that byte to the first column the
1896749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  tab appears at and the next value in the map will have been incremented
1906749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  more than once.
1916749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
1926749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// If a byte is the first in a sequence of bytes that together map to a single
1936749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  entity in the output, then the array will map that byte to the appropriate
1946749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  column while the subsequent bytes will be -1.
1956749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
1966749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// The last element in the array does not correspond to any byte in the input
1976749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  and instead is the number of columns needed to display the source
1986749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
1996749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// example: (given a tabstop of 8)
2006749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
2016749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///    "a \t \u3042" -> {0,1,2,8,9,-1,-1,11}
2026749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
2036b4f50662a1857d5203254fb2c52975e6f30fc90James Dennett///  (\\u3042 is represented in UTF-8 by three bytes and takes two columns to
2046749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///   display)
205d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramerstatic void byteToColumn(StringRef SourceLine, unsigned TabStop,
206d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramer                         SmallVectorImpl<int> &out) {
2076749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  out.clear();
2086749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2096749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (SourceLine.empty()) {
2106749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    out.resize(1u,0);
2116749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return;
2126749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
2136749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2146749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  out.resize(SourceLine.size()+1, -1);
2156749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2166749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  int columns = 0;
2176749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  size_t i = 0;
2186749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  while (i<SourceLine.size()) {
2196749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    out[i] = columns;
2206749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    std::pair<SmallString<16>,bool> res
2216749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      = printableTextForNextCharacter(SourceLine, &i, TabStop);
2226749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    columns += llvm::sys::locale::columnWidth(res.first);
2236749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
2246749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  out.back() = columns;
2256749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell}
2266749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2276749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// This function takes a raw source line and produces a mapping from columns
2286749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  to the byte of the source line that produced the character displaying at
2296749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///  that column. This is the inverse of the mapping produced by byteToColumn()
2306749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
2316749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// The last element in the array is the number of bytes in the source string
2326749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
2336749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// example: (given a tabstop of 8)
2346749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
2356749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///    "a \t \u3042" -> {0,1,2,-1,-1,-1,-1,-1,3,4,-1,7}
2366749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///
2376b4f50662a1857d5203254fb2c52975e6f30fc90James Dennett///  (\\u3042 is represented in UTF-8 by three bytes and takes two columns to
2386749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell///   display)
239d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramerstatic void columnToByte(StringRef SourceLine, unsigned TabStop,
2406749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                         SmallVectorImpl<int> &out) {
2416749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  out.clear();
2426749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2436749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (SourceLine.empty()) {
2446749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    out.resize(1u, 0);
2456749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return;
2466749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
2476749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2486749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  int columns = 0;
2496749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  size_t i = 0;
2506749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  while (i<SourceLine.size()) {
2516749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    out.resize(columns+1, -1);
2526749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    out.back() = i;
2536749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    std::pair<SmallString<16>,bool> res
2546749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      = printableTextForNextCharacter(SourceLine, &i, TabStop);
2556749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    columns += llvm::sys::locale::columnWidth(res.first);
2566749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
2576749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  out.resize(columns+1, -1);
2586749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  out.back() = i;
2596749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell}
2606749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2616749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrellstruct SourceColumnMap {
2626749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  SourceColumnMap(StringRef SourceLine, unsigned TabStop)
2636749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  : m_SourceLine(SourceLine) {
2646749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2656749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    ::byteToColumn(SourceLine, TabStop, m_byteToColumn);
2666749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    ::columnToByte(SourceLine, TabStop, m_columnToByte);
2676749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2686749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(m_byteToColumn.size()==SourceLine.size()+1);
2696749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(0 < m_byteToColumn.size() && 0 < m_columnToByte.size());
2706749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(m_byteToColumn.size()
2716749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell           == static_cast<unsigned>(m_columnToByte.back()+1));
2726749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(static_cast<unsigned>(m_byteToColumn.back()+1)
2736749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell           == m_columnToByte.size());
2746749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
2756749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  int columns() const { return m_byteToColumn.back(); }
2766749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  int bytes() const { return m_columnToByte.back(); }
2776749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  int byteToColumn(int n) const {
2786749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(0<=n && n<static_cast<int>(m_byteToColumn.size()));
2796749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return m_byteToColumn[n];
2806749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
2816749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  int columnToByte(int n) const {
2826749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    assert(0<=n && n<static_cast<int>(m_columnToByte.size()));
2836749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return m_columnToByte[n];
2846749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
2856749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  StringRef getSourceLine() const {
2866749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return m_SourceLine;
2876749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
2886749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2896749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrellprivate:
2906749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  const std::string m_SourceLine;
2916749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  SmallVector<int,200> m_byteToColumn;
2926749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  SmallVector<int,200> m_columnToByte;
2936749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell};
2946749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
2956749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell// used in assert in selectInterestingSourceRegion()
2966749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrellnamespace {
2976749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrellstruct char_out_of_range {
2986749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  const char lower,upper;
2996749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  char_out_of_range(char lower, char upper) :
3006749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    lower(lower), upper(upper) {}
3016749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  bool operator()(char c) { return c < lower || upper < c; }
3026749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell};
3036749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell}
3046749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
305db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief When the source code line we want to print is too long for
306db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// the terminal, select the "interesting" region.
3077531f571808201d44002fa38b67ee0a81e5ae936Chandler Carruthstatic void selectInterestingSourceRegion(std::string &SourceLine,
308db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                                          std::string &CaretLine,
309db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                                          std::string &FixItInsertionLine,
3106749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                          unsigned Columns,
3116749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                          const SourceColumnMap &map) {
3126749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned MaxColumns = std::max<unsigned>(map.columns(),
3136749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                           std::max(CaretLine.size(),
3146749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                                    FixItInsertionLine.size()));
3156749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // if the number of columns is less than the desired number we're done
3166749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (MaxColumns <= Columns)
3176749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return;
3186749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
3196749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // no special characters allowed in CaretLine or FixItInsertionLine
3206749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(CaretLine.end() ==
3216749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell         std::find_if(CaretLine.begin(), CaretLine.end(),
3226749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell         char_out_of_range(' ','~')));
3236749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(FixItInsertionLine.end() ==
3246749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell         std::find_if(FixItInsertionLine.begin(), FixItInsertionLine.end(),
3256749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell         char_out_of_range(' ','~')));
3266749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
327db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Find the slice that we need to display the full caret line
328db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // correctly.
329db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  unsigned CaretStart = 0, CaretEnd = CaretLine.size();
330db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  for (; CaretStart != CaretEnd; ++CaretStart)
3314031a376275ccf9f76eae2efeb26ee64c4c5780aSeth Cantrell    if (!isspace(static_cast<unsigned char>(CaretLine[CaretStart])))
332db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      break;
333db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
334db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  for (; CaretEnd != CaretStart; --CaretEnd)
3354031a376275ccf9f76eae2efeb26ee64c4c5780aSeth Cantrell    if (!isspace(static_cast<unsigned char>(CaretLine[CaretEnd - 1])))
336db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      break;
337db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
3386749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // caret has already been inserted into CaretLine so the above whitespace
3396749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // check is guaranteed to include the caret
340db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
341db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // If we have a fix-it line, make sure the slice includes all of the
342db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // fix-it information.
343db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (!FixItInsertionLine.empty()) {
344db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    unsigned FixItStart = 0, FixItEnd = FixItInsertionLine.size();
345db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    for (; FixItStart != FixItEnd; ++FixItStart)
3464031a376275ccf9f76eae2efeb26ee64c4c5780aSeth Cantrell      if (!isspace(static_cast<unsigned char>(FixItInsertionLine[FixItStart])))
347db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        break;
348db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
349db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    for (; FixItEnd != FixItStart; --FixItEnd)
3504031a376275ccf9f76eae2efeb26ee64c4c5780aSeth Cantrell      if (!isspace(static_cast<unsigned char>(FixItInsertionLine[FixItEnd - 1])))
351db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        break;
352db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
3536749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    CaretStart = std::min(FixItStart, CaretStart);
3546749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    CaretEnd = std::max(FixItEnd, CaretEnd);
355db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
356db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
357c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell  // CaretEnd may have been set at the middle of a character
358c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell  // If it's not at a character's first column then advance it past the current
359c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell  //   character.
360c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell  while (static_cast<int>(CaretEnd) < map.columns() &&
361c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell         -1 == map.columnToByte(CaretEnd))
362c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell    ++CaretEnd;
363c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell
364c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell  assert((static_cast<int>(CaretStart) > map.columns() ||
365c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell          -1!=map.columnToByte(CaretStart)) &&
366c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell         "CaretStart must not point to a column in the middle of a source"
367c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell         " line character");
368c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell  assert((static_cast<int>(CaretEnd) > map.columns() ||
369c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell          -1!=map.columnToByte(CaretEnd)) &&
370c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell         "CaretEnd must not point to a column in the middle of a source line"
371c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell         " character");
372c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell
373db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // CaretLine[CaretStart, CaretEnd) contains all of the interesting
374db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // parts of the caret line. While this slice is smaller than the
375db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // number of columns we have, try to grow the slice to encompass
376db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // more context.
377db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
3786749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned SourceStart = map.columnToByte(std::min<unsigned>(CaretStart,
3796749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                                             map.columns()));
3806749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned SourceEnd = map.columnToByte(std::min<unsigned>(CaretEnd,
3816749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                                           map.columns()));
3826749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
3836749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned CaretColumnsOutsideSource = CaretEnd-CaretStart
3846749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    - (map.byteToColumn(SourceEnd)-map.byteToColumn(SourceStart));
3856749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
3866749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  char const *front_ellipse = "  ...";
3876749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  char const *front_space   = "     ";
3886749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  char const *back_ellipse = "...";
3896749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned ellipses_space = strlen(front_ellipse) + strlen(back_ellipse);
390db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
391db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  unsigned TargetColumns = Columns;
3926749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // Give us extra room for the ellipses
3936749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  //  and any of the caret line that extends past the source
3946749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (TargetColumns > ellipses_space+CaretColumnsOutsideSource)
3956749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    TargetColumns -= ellipses_space+CaretColumnsOutsideSource;
3966749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
3976749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  while (SourceStart>0 || SourceEnd<SourceLine.size()) {
398db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    bool ExpandedRegion = false;
3996749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
4006749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    if (SourceStart>0) {
4016749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      unsigned NewStart = SourceStart-1;
402db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
403db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // Skip over any whitespace we see here; we're looking for
404db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // another bit of interesting text.
4056749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      while (NewStart &&
4064031a376275ccf9f76eae2efeb26ee64c4c5780aSeth Cantrell             (map.byteToColumn(NewStart)==-1 ||
4074031a376275ccf9f76eae2efeb26ee64c4c5780aSeth Cantrell             isspace(static_cast<unsigned char>(SourceLine[NewStart]))))
408db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        --NewStart;
409db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
410db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // Skip over this bit of "interesting" text.
4116749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      while (NewStart &&
4124031a376275ccf9f76eae2efeb26ee64c4c5780aSeth Cantrell             (map.byteToColumn(NewStart)!=-1 &&
4134031a376275ccf9f76eae2efeb26ee64c4c5780aSeth Cantrell             !isspace(static_cast<unsigned char>(SourceLine[NewStart]))))
414db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        --NewStart;
415db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
416db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // Move up to the non-whitespace character we just saw.
417db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      if (NewStart)
418db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        ++NewStart;
419db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
4206749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      unsigned NewColumns = map.byteToColumn(SourceEnd) -
4216749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                              map.byteToColumn(NewStart);
4226749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      if (NewColumns <= TargetColumns) {
4236749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell        SourceStart = NewStart;
424db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        ExpandedRegion = true;
425db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      }
426db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    }
427db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
4286749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    if (SourceEnd<SourceLine.size()) {
4296749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      unsigned NewEnd = SourceEnd+1;
430db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
431db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // Skip over any whitespace we see here; we're looking for
432db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // another bit of interesting text.
4336749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      while (NewEnd<SourceLine.size() &&
4344031a376275ccf9f76eae2efeb26ee64c4c5780aSeth Cantrell             (map.byteToColumn(NewEnd)==-1 ||
4354031a376275ccf9f76eae2efeb26ee64c4c5780aSeth Cantrell             isspace(static_cast<unsigned char>(SourceLine[NewEnd]))))
436db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        ++NewEnd;
437db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
438db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // Skip over this bit of "interesting" text.
4396749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      while (NewEnd<SourceLine.size() &&
4404031a376275ccf9f76eae2efeb26ee64c4c5780aSeth Cantrell             (map.byteToColumn(NewEnd)!=-1 &&
4414031a376275ccf9f76eae2efeb26ee64c4c5780aSeth Cantrell             !isspace(static_cast<unsigned char>(SourceLine[NewEnd]))))
442db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        ++NewEnd;
443db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
4446749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      unsigned NewColumns = map.byteToColumn(NewEnd) -
4456749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                              map.byteToColumn(SourceStart);
4466749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      if (NewColumns <= TargetColumns) {
4476749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell        SourceEnd = NewEnd;
448db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        ExpandedRegion = true;
449db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      }
450db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    }
451db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
452db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (!ExpandedRegion)
453db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      break;
454db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
455db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
4566749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  CaretStart = map.byteToColumn(SourceStart);
4576749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  CaretEnd = map.byteToColumn(SourceEnd) + CaretColumnsOutsideSource;
4586749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
459db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // [CaretStart, CaretEnd) is the slice we want. Update the various
460db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // output lines to show only this slice, with two-space padding
461db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // before the lines so that it looks nicer.
4626749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
4636749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(CaretStart!=(unsigned)-1 && CaretEnd!=(unsigned)-1 &&
4646749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell         SourceStart!=(unsigned)-1 && SourceEnd!=(unsigned)-1);
4656749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(SourceStart <= SourceEnd);
4666749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(CaretStart <= CaretEnd);
4676749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
4686749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned BackColumnsRemoved
4696749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    = map.byteToColumn(SourceLine.size())-map.byteToColumn(SourceEnd);
4706749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned FrontColumnsRemoved = CaretStart;
4716749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned ColumnsKept = CaretEnd-CaretStart;
4726749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
4736749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // We checked up front that the line needed truncation
4746749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(FrontColumnsRemoved+ColumnsKept+BackColumnsRemoved > Columns);
4756749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
4766749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // The line needs some trunctiona, and we'd prefer to keep the front
4776749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  //  if possible, so remove the back
4786749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (BackColumnsRemoved)
4796749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    SourceLine.replace(SourceEnd, std::string::npos, back_ellipse);
4806749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
4816749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // If that's enough then we're done
4826749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (FrontColumnsRemoved+ColumnsKept <= Columns)
4836749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return;
4846749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
4856749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // Otherwise remove the front as well
4866749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (FrontColumnsRemoved) {
4876749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    SourceLine.replace(0, SourceStart, front_ellipse);
4886749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    CaretLine.replace(0, CaretStart, front_space);
4896749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    if (!FixItInsertionLine.empty())
4906749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      FixItInsertionLine.replace(0, CaretStart, front_space);
491db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
492db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
493db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
494db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief Skip over whitespace in the string, starting at the given
495db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// index.
496db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth///
497db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \returns The index of the first non-whitespace character that is
498db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// greater than or equal to Idx or, if no such character exists,
499db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// returns the end of the string.
500db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic unsigned skipWhitespace(unsigned Idx, StringRef Str, unsigned Length) {
501db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  while (Idx < Length && isspace(Str[Idx]))
502db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    ++Idx;
503db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  return Idx;
504db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
505db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
506db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief If the given character is the start of some kind of
507db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// balanced punctuation (e.g., quotes or parentheses), return the
508db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// character that will terminate the punctuation.
509db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth///
510db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \returns The ending punctuation character, if any, or the NULL
511db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// character if the input character does not start any punctuation.
512db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic inline char findMatchingPunctuation(char c) {
513db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  switch (c) {
514db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  case '\'': return '\'';
515db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  case '`': return '\'';
516db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  case '"':  return '"';
517db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  case '(':  return ')';
518db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  case '[': return ']';
519db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  case '{': return '}';
520db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  default: break;
521db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
522db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
523db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  return 0;
524db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
525db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
526db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief Find the end of the word starting at the given offset
527db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// within a string.
528db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth///
529db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \returns the index pointing one character past the end of the
530db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// word.
531db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic unsigned findEndOfWord(unsigned Start, StringRef Str,
532db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                              unsigned Length, unsigned Column,
533db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                              unsigned Columns) {
534db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  assert(Start < Str.size() && "Invalid start position!");
535db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  unsigned End = Start + 1;
536db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
537db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // If we are already at the end of the string, take that as the word.
538db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (End == Str.size())
539db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    return End;
540db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
541db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Determine if the start of the string is actually opening
542db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // punctuation, e.g., a quote or parentheses.
543db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  char EndPunct = findMatchingPunctuation(Str[Start]);
544db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (!EndPunct) {
545db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // This is a normal word. Just find the first space character.
546db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    while (End < Length && !isspace(Str[End]))
547db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      ++End;
548db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    return End;
549db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
550db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
551db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // We have the start of a balanced punctuation sequence (quotes,
552db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // parentheses, etc.). Determine the full sequence is.
553f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith  SmallString<16> PunctuationEndStack;
554db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  PunctuationEndStack.push_back(EndPunct);
555db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  while (End < Length && !PunctuationEndStack.empty()) {
556db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (Str[End] == PunctuationEndStack.back())
557db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      PunctuationEndStack.pop_back();
558db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    else if (char SubEndPunct = findMatchingPunctuation(Str[End]))
559db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      PunctuationEndStack.push_back(SubEndPunct);
560db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
561db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    ++End;
562db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
563db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
564db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Find the first space character after the punctuation ended.
565db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  while (End < Length && !isspace(Str[End]))
566db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    ++End;
567db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
568db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  unsigned PunctWordLength = End - Start;
569db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (// If the word fits on this line
570db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      Column + PunctWordLength <= Columns ||
571db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // ... or the word is "short enough" to take up the next line
572db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // without too much ugly white space
573db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      PunctWordLength < Columns/3)
574db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    return End; // Take the whole thing as a single "word".
575db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
576db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // The whole quoted/parenthesized string is too long to print as a
577db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // single "word". Instead, find the "word" that starts just after
578db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // the punctuation and use that end-point instead. This will recurse
579db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // until it finds something small enough to consider a word.
580db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  return findEndOfWord(Start + 1, Str, Length, Column + 1, Columns);
581db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
582db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
583db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief Print the given string to a stream, word-wrapping it to
584db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// some number of columns in the process.
585db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth///
586db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param OS the stream to which the word-wrapping string will be
587db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// emitted.
588db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Str the string to word-wrap and output.
589db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Columns the number of columns to word-wrap to.
590db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Column the column number at which the first character of \p
591db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// Str will be printed. This will be non-zero when part of the first
592db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// line has already been printed.
593b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu/// \param Bold if the current text should be bold
594db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Indentation the number of spaces to indent any lines beyond
595db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// the first line.
596db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \returns true if word-wrapping was required, or false if the
597db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// string fit on the first line.
598db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic bool printWordWrapped(raw_ostream &OS, StringRef Str,
599db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                             unsigned Columns,
600db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                             unsigned Column = 0,
601b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu                             bool Bold = false,
602db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                             unsigned Indentation = WordWrapIndentation) {
603db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  const unsigned Length = std::min(Str.find('\n'), Str.size());
604246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu  bool TextNormal = true;
605db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
606db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // The string used to indent each line.
607f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith  SmallString<16> IndentStr;
608db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  IndentStr.assign(Indentation, ' ');
609db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  bool Wrapped = false;
610db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  for (unsigned WordStart = 0, WordEnd; WordStart < Length;
611db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth       WordStart = WordEnd) {
612db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // Find the beginning of the next word.
613db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    WordStart = skipWhitespace(WordStart, Str, Length);
614db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (WordStart == Length)
615db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      break;
616db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
617db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // Find the end of this word.
618db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    WordEnd = findEndOfWord(WordStart, Str, Length, Column, Columns);
619db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
620db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // Does this word fit on the current line?
621db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    unsigned WordLength = WordEnd - WordStart;
622db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (Column + WordLength < Columns) {
623db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // This word fits on the current line; print it there.
624db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      if (WordStart) {
625db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        OS << ' ';
626db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        Column += 1;
627db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      }
628246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu      applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength),
629b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu                                TextNormal, Bold);
630db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      Column += WordLength;
631db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      continue;
632db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    }
633db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
634db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // This word does not fit on the current line, so wrap to the next
635db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // line.
636db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS << '\n';
637db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS.write(&IndentStr[0], Indentation);
638246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu    applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength),
639b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu                              TextNormal, Bold);
640db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    Column = Indentation + WordLength;
641db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    Wrapped = true;
642db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
643db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
644db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Append any remaning text from the message with its existing formatting.
645b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu  applyTemplateHighlighting(OS, Str.substr(Length), TextNormal, Bold);
646246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu
647246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu  assert(TextNormal && "Text highlighted at end of diagnostic message.");
648db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
649db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  return Wrapped;
650db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
651db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
652db463bb2e4a9751f4cbe53996db751e1985ee966Chandler CarruthTextDiagnostic::TextDiagnostic(raw_ostream &OS,
653db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                               const LangOptions &LangOpts,
65421a869aace45586125238fde88c477b330618a0bChandler Carruth                               const DiagnosticOptions &DiagOpts)
65516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  : DiagnosticRenderer(LangOpts, DiagOpts), OS(OS) {}
656db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
6572898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted KremenekTextDiagnostic::~TextDiagnostic() {}
658db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
6592898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid
6602898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted KremenekTextDiagnostic::emitDiagnosticMessage(SourceLocation Loc,
6612898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                      PresumedLoc PLoc,
6622898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                      DiagnosticsEngine::Level Level,
6632898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                      StringRef Message,
6642898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek                                      ArrayRef<clang::CharSourceRange> Ranges,
66516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                      const SourceManager *SM,
6668be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek                                      DiagOrStoredDiag D) {
667db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  uint64_t StartOfLocationInfo = OS.tell();
668db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
6692898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  // Emit the location of this particular diagnostic.
67016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  if (Loc.isValid())
67116afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis    emitDiagnosticLoc(Loc, PLoc, Level, Ranges, *SM);
6722898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
673db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (DiagOpts.ShowColors)
674db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS.resetColor();
6752898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek
676db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  printDiagnosticLevel(OS, Level, DiagOpts.ShowColors);
677db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  printDiagnosticMessage(OS, Level, Message,
678db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                         OS.tell() - StartOfLocationInfo,
679db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                         DiagOpts.MessageLength, DiagOpts.ShowColors);
680db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
681db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
6826ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/*static*/ void
6836ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler CarruthTextDiagnostic::printDiagnosticLevel(raw_ostream &OS,
6846ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth                                     DiagnosticsEngine::Level Level,
6856ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth                                     bool ShowColors) {
6866ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  if (ShowColors) {
6876ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    // Print diagnostic category in bold and color
6886ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    switch (Level) {
6896ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    case DiagnosticsEngine::Ignored:
6906ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      llvm_unreachable("Invalid diagnostic type");
6916ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    case DiagnosticsEngine::Note:    OS.changeColor(noteColor, true); break;
6926ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    case DiagnosticsEngine::Warning: OS.changeColor(warningColor, true); break;
6936ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    case DiagnosticsEngine::Error:   OS.changeColor(errorColor, true); break;
6946ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    case DiagnosticsEngine::Fatal:   OS.changeColor(fatalColor, true); break;
6956ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    }
6966ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  }
6976ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
6986ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  switch (Level) {
6996ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticsEngine::Ignored:
7006ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    llvm_unreachable("Invalid diagnostic type");
7016ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticsEngine::Note:    OS << "note: "; break;
7026ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticsEngine::Warning: OS << "warning: "; break;
7036ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticsEngine::Error:   OS << "error: "; break;
7046ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticsEngine::Fatal:   OS << "fatal error: "; break;
7056ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  }
7066ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
7076ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  if (ShowColors)
7086ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    OS.resetColor();
7096ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth}
7106ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
7116ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/*static*/ void
7126ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler CarruthTextDiagnostic::printDiagnosticMessage(raw_ostream &OS,
7136ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth                                       DiagnosticsEngine::Level Level,
7146ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth                                       StringRef Message,
7156ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth                                       unsigned CurrentColumn, unsigned Columns,
7166ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth                                       bool ShowColors) {
717b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu  bool Bold = false;
7186ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  if (ShowColors) {
7196ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    // Print warnings, errors and fatal errors in bold, no color
7206ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    switch (Level) {
721b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu    case DiagnosticsEngine::Warning:
722b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu    case DiagnosticsEngine::Error:
723b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu    case DiagnosticsEngine::Fatal:
724b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu      OS.changeColor(savedColor, true);
725b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu      Bold = true;
726b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu      break;
7276ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    default: break; //don't bold notes
7286ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    }
7296ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  }
7306ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
7316ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  if (Columns)
732b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu    printWordWrapped(OS, Message, Columns, CurrentColumn, Bold);
73350badd523b9b90c0731423d002b13a00bf754036David Blaikie  else {
73450badd523b9b90c0731423d002b13a00bf754036David Blaikie    bool Normal = true;
735b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu    applyTemplateHighlighting(OS, Message, Normal, Bold);
73650badd523b9b90c0731423d002b13a00bf754036David Blaikie    assert(Normal && "Formatting should have returned to normal");
73750badd523b9b90c0731423d002b13a00bf754036David Blaikie  }
7386ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
7396ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  if (ShowColors)
7406ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    OS.resetColor();
7416ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  OS << '\n';
7426ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth}
7436ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
7446ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/// \brief Print out the file/line/column information and include trace.
7456ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth///
7466ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/// This method handlen the emission of the diagnostic location information.
7476ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/// This includes extracting as much location information as is present for
7486ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/// the diagnostic and printing it, as well as any include stack or source
7496ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/// ranges necessary.
7507531f571808201d44002fa38b67ee0a81e5ae936Chandler Carruthvoid TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
7516ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth                                       DiagnosticsEngine::Level Level,
75216afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                       ArrayRef<CharSourceRange> Ranges,
75316afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                       const SourceManager &SM) {
7546ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  if (PLoc.isInvalid()) {
7556ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    // At least print the file name if available:
7566ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    FileID FID = SM.getFileID(Loc);
7576ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    if (!FID.isInvalid()) {
7586ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      const FileEntry* FE = SM.getFileEntryForID(FID);
7596ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      if (FE && FE->getName()) {
7606ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        OS << FE->getName();
7616ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        if (FE->getDevice() == 0 && FE->getInode() == 0
7626ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth            && FE->getFileMode() == 0) {
7636ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth          // in PCH is a guess, but a good one:
7646ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth          OS << " (in PCH)";
7656ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        }
7666ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        OS << ": ";
7676ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      }
7686ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    }
7696ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    return;
7706ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  }
7716ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  unsigned LineNo = PLoc.getLine();
7726ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
7736ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  if (!DiagOpts.ShowLocation)
7746ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    return;
7756ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
7766ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  if (DiagOpts.ShowColors)
7776ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    OS.changeColor(savedColor, true);
7786ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
7796ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  OS << PLoc.getFilename();
7806ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  switch (DiagOpts.Format) {
7816ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticOptions::Clang: OS << ':'  << LineNo; break;
7826ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticOptions::Msvc:  OS << '('  << LineNo; break;
7836ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticOptions::Vi:    OS << " +" << LineNo; break;
7846ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  }
7856ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
7866ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  if (DiagOpts.ShowColumn)
7876ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    // Compute the column number.
7886ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    if (unsigned ColNo = PLoc.getColumn()) {
7896ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      if (DiagOpts.Format == DiagnosticOptions::Msvc) {
7906ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        OS << ',';
7916ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        ColNo--;
7926ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      } else
7936ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        OS << ':';
7946ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      OS << ColNo;
7956ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    }
7966ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  switch (DiagOpts.Format) {
7976ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticOptions::Clang:
7986ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticOptions::Vi:    OS << ':';    break;
7996ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  case DiagnosticOptions::Msvc:  OS << ") : "; break;
8006ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  }
8016ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8026ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  if (DiagOpts.ShowSourceRanges && !Ranges.empty()) {
8036ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    FileID CaretFileID =
8046ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      SM.getFileID(SM.getExpansionLoc(Loc));
8056ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    bool PrintedRange = false;
8066ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8076ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    for (ArrayRef<CharSourceRange>::const_iterator RI = Ranges.begin(),
8086ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth         RE = Ranges.end();
8096ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth         RI != RE; ++RI) {
8106ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // Ignore invalid ranges.
8116ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      if (!RI->isValid()) continue;
8126ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8136ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      SourceLocation B = SM.getExpansionLoc(RI->getBegin());
8146ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      SourceLocation E = SM.getExpansionLoc(RI->getEnd());
8156ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8166ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // If the End location and the start location are the same and are a
8176ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // macro location, then the range was something that came from a
8186ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // macro expansion or _Pragma.  If this is an object-like macro, the
8196ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // best we can do is to highlight the range.  If this is a
8206ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // function-like macro, we'd also like to highlight the arguments.
8216ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      if (B == E && RI->getEnd().isMacroID())
8226ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        E = SM.getExpansionRange(RI->getEnd()).second;
8236ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8246ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
8256ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
8266ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8276ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // If the start or end of the range is in another file, just discard
8286ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // it.
8296ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      if (BInfo.first != CaretFileID || EInfo.first != CaretFileID)
8306ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        continue;
8316ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8326ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // Add in the length of the token, so that we cover multi-char
8336ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      // tokens.
8346ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      unsigned TokSize = 0;
8356ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      if (RI->isTokenRange())
8366ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        TokSize = Lexer::MeasureTokenLength(E, SM, LangOpts);
8376ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8386ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':'
8396ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        << SM.getColumnNumber(BInfo.first, BInfo.second) << '-'
8406ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        << SM.getLineNumber(EInfo.first, EInfo.second) << ':'
8416ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        << (SM.getColumnNumber(EInfo.first, EInfo.second)+TokSize)
8426ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth        << '}';
8436ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      PrintedRange = true;
8446ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    }
8456ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8466ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth    if (PrintedRange)
8476ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth      OS << ':';
8486ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  }
8496ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth  OS << ' ';
8506ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth}
8516ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth
8522898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid TextDiagnostic::emitBasicNote(StringRef Message) {
8532898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  // FIXME: Emit this as a real note diagnostic.
8542898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  // FIXME: Format an actual diagnostic rather than a hard coded string.
8552898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  OS << "note: " << Message << "\n";
8562898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek}
857db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
8582898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
85916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                         PresumedLoc PLoc,
86016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                         const SourceManager &SM) {
8612898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  if (DiagOpts.ShowLocation)
8622898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek    OS << "In file included from " << PLoc.getFilename() << ':'
8632898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek       << PLoc.getLine() << ":\n";
8642898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek  else
8652898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek    OS << "In included file:\n";
866db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
867db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
868db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief Emit a code snippet and caret line.
869db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth///
870db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// This routine emits a single line's code snippet and caret line..
871db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth///
872db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Loc The location for the caret.
873db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Ranges The underlined ranges for this code snippet.
874db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Hints The FixIt hints active for this diagnostic.
8757531f571808201d44002fa38b67ee0a81e5ae936Chandler Carruthvoid TextDiagnostic::emitSnippetAndCaret(
8764ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth    SourceLocation Loc, DiagnosticsEngine::Level Level,
877db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    SmallVectorImpl<CharSourceRange>& Ranges,
87816afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis    ArrayRef<FixItHint> Hints,
87916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis    const SourceManager &SM) {
880db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  assert(!Loc.isInvalid() && "must have a valid source location here");
881db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  assert(Loc.isFileID() && "must have a file location here");
882db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
8834ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth  // If caret diagnostics are enabled and we have location, we want to
8844ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth  // emit the caret.  However, we only do this if the location moved
8854ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth  // from the last diagnostic, if the last diagnostic was a note that
8864ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth  // was part of a different warning or error diagnostic, or if the
8874ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth  // diagnostic has ranges.  We don't want to emit the same caret
8884ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth  // multiple times if one loc has multiple diagnostics.
8894ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth  if (!DiagOpts.ShowCarets)
8904ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth    return;
8914ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth  if (Loc == LastLoc && Ranges.empty() && Hints.empty() &&
8924ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth      (LastLevel != DiagnosticsEngine::Note || Level == LastLevel))
8934ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth    return;
8944ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth
895db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Decompose the location into a FID/Offset pair.
896db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
897db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  FileID FID = LocInfo.first;
898db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  unsigned FileOffset = LocInfo.second;
899db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
900db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Get information about the buffer it points into.
901db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  bool Invalid = false;
90240d8e971a32a23856ce1ab0106ae75cf4b92ca9dNico Weber  const char *BufStart = SM.getBufferData(FID, &Invalid).data();
903db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (Invalid)
904db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    return;
905db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
906db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  unsigned LineNo = SM.getLineNumber(FID, FileOffset);
907db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
908db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
909db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Rewind from the current position to the start of the line.
910db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  const char *TokPtr = BufStart+FileOffset;
911db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based.
912db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
913db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
914db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Compute the line end.  Scan forward from the error position to the end of
915db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // the line.
916db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  const char *LineEnd = TokPtr;
91740d8e971a32a23856ce1ab0106ae75cf4b92ca9dNico Weber  while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')
918db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    ++LineEnd;
919db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
920db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Copy the line of code into an std::string for ease of manipulation.
921db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  std::string SourceLine(LineStart, LineEnd);
922db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
923db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Create a line for the caret that is filled with spaces that is the same
924db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // length as the line of source code.
925db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  std::string CaretLine(LineEnd-LineStart, ' ');
926db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
9276749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  const SourceColumnMap sourceColMap(SourceLine, DiagOpts.TabStop);
9286749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
929db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Highlight all of the characters covered by Ranges with ~ characters.
930db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
931db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                                                  E = Ranges.end();
932db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth       I != E; ++I)
93316afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis    highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM);
934db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
935db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Next, insert the caret itself.
9366749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  ColNo = sourceColMap.byteToColumn(ColNo-1);
9376749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (CaretLine.size()<ColNo+1)
9386749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    CaretLine.resize(ColNo+1, ' ');
9396749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  CaretLine[ColNo] = '^';
940e9a3b76ba589a8a884e978273beaed0d97cf9861Seth Cantrell
9416749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  std::string FixItInsertionLine = buildFixItInsertionLine(LineNo,
9426749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                                           sourceColMap,
94316afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                                           Hints, SM);
9446749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
9456749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // If the source line is too long for our terminal, select only the
9466749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  // "interesting" source region within that line.
9476749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned Columns = DiagOpts.MessageLength;
9486749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (Columns)
9496749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine,
9506749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                  Columns, sourceColMap);
951db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
952db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // If we are in -fdiagnostics-print-source-range-info mode, we are trying
953db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // to produce easily machine parsable output.  Add a space before the
954db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // source line and the caret to make it trivial to tell the main diagnostic
955db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // line from what the user is intended to see.
956db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (DiagOpts.ShowSourceRanges) {
957db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    SourceLine = ' ' + SourceLine;
958db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    CaretLine = ' ' + CaretLine;
959db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
960db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
961db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Finally, remove any blank spaces from the end of CaretLine.
962db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  while (CaretLine[CaretLine.size()-1] == ' ')
963db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    CaretLine.erase(CaretLine.end()-1);
964db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
965db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Emit what we have computed.
9666749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  emitSnippet(SourceLine);
967db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
968db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (DiagOpts.ShowColors)
969db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS.changeColor(caretColor, true);
970db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  OS << CaretLine << '\n';
971db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (DiagOpts.ShowColors)
972db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS.resetColor();
973db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
974db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (!FixItInsertionLine.empty()) {
975db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (DiagOpts.ShowColors)
976db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // Print fixit line in color
977db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      OS.changeColor(fixitColor, false);
978db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (DiagOpts.ShowSourceRanges)
979db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      OS << ' ';
980db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS << FixItInsertionLine << '\n';
981db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (DiagOpts.ShowColors)
982db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      OS.resetColor();
983db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
984db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
985db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Print out any parseable fixit information requested by the options.
98616afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  emitParseableFixits(Hints, SM);
987db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
988db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
989d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramervoid TextDiagnostic::emitSnippet(StringRef line) {
9906749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (line.empty())
9916749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    return;
9926749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
9936749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  size_t i = 0;
9946749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
9956749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  std::string to_print;
9966749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  bool print_reversed = false;
9976749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
9986749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  while (i<line.size()) {
9996749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    std::pair<SmallString<16>,bool> res
10006749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell        = printableTextForNextCharacter(line, &i, DiagOpts.TabStop);
10016749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    bool was_printable = res.second;
10026749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
100340d8e971a32a23856ce1ab0106ae75cf4b92ca9dNico Weber    if (DiagOpts.ShowColors && was_printable == print_reversed) {
10046749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      if (print_reversed)
10056749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell        OS.reverseColor();
10066749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      OS << to_print;
10076749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      to_print.clear();
10086749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      if (DiagOpts.ShowColors)
10096749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell        OS.resetColor();
10106749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    }
10116749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
10126749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    print_reversed = !was_printable;
10136749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    to_print += res.first.str();
10146749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  }
10156749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
10166749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (print_reversed && DiagOpts.ShowColors)
10176749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    OS.reverseColor();
10186749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  OS << to_print;
10196749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (print_reversed && DiagOpts.ShowColors)
10206749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    OS.resetColor();
10216749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
10226749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  OS << '\n';
10236749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell}
10246749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1025db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief Highlight a SourceRange (with ~'s) for any characters on LineNo.
10267531f571808201d44002fa38b67ee0a81e5ae936Chandler Carruthvoid TextDiagnostic::highlightRange(const CharSourceRange &R,
1027db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth                                    unsigned LineNo, FileID FID,
10286749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell                                    const SourceColumnMap &map,
102916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                    std::string &CaretLine,
103016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                    const SourceManager &SM) {
1031db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (!R.isValid()) return;
1032db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1033db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  SourceLocation Begin = SM.getExpansionLoc(R.getBegin());
1034db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  SourceLocation End = SM.getExpansionLoc(R.getEnd());
1035db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1036db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // If the End location and the start location are the same and are a macro
1037db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // location, then the range was something that came from a macro expansion
1038db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // or _Pragma.  If this is an object-like macro, the best we can do is to
1039db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // highlight the range.  If this is a function-like macro, we'd also like to
1040db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // highlight the arguments.
1041db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (Begin == End && R.getEnd().isMacroID())
1042db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    End = SM.getExpansionRange(R.getEnd()).second;
1043db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1044db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  unsigned StartLineNo = SM.getExpansionLineNumber(Begin);
1045db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (StartLineNo > LineNo || SM.getFileID(Begin) != FID)
1046db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    return;  // No intersection.
1047db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1048db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  unsigned EndLineNo = SM.getExpansionLineNumber(End);
1049db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (EndLineNo < LineNo || SM.getFileID(End) != FID)
1050db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    return;  // No intersection.
1051db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1052db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Compute the column number of the start.
1053db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  unsigned StartColNo = 0;
1054db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (StartLineNo == LineNo) {
1055db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    StartColNo = SM.getExpansionColumnNumber(Begin);
1056db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (StartColNo) --StartColNo;  // Zero base the col #.
1057db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
1058db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1059db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Compute the column number of the end.
10606749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned EndColNo = map.getSourceLine().size();
1061db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (EndLineNo == LineNo) {
1062db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    EndColNo = SM.getExpansionColumnNumber(End);
1063db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (EndColNo) {
1064db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      --EndColNo;  // Zero base the col #.
1065db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1066db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // Add in the length of the token, so that we cover multi-char tokens if
1067db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // this is a token range.
1068db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      if (R.isTokenRange())
1069db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        EndColNo += Lexer::MeasureTokenLength(End, SM, LangOpts);
1070db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    } else {
1071db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      EndColNo = CaretLine.size();
1072db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    }
1073db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
1074db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1075db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  assert(StartColNo <= EndColNo && "Invalid range!");
1076db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1077db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Check that a token range does not highlight only whitespace.
1078db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (R.isTokenRange()) {
1079db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // Pick the first non-whitespace column.
10806749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    while (StartColNo < map.getSourceLine().size() &&
10816749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell           (map.getSourceLine()[StartColNo] == ' ' ||
10826749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell            map.getSourceLine()[StartColNo] == '\t'))
1083db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      ++StartColNo;
1084db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1085db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // Pick the last non-whitespace column.
10866749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    if (EndColNo > map.getSourceLine().size())
10876749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell      EndColNo = map.getSourceLine().size();
1088db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    while (EndColNo-1 &&
10896749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell           (map.getSourceLine()[EndColNo-1] == ' ' ||
10906749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell            map.getSourceLine()[EndColNo-1] == '\t'))
1091db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      --EndColNo;
1092db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1093db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // If the start/end passed each other, then we are trying to highlight a
1094db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // range that just exists in whitespace, which must be some sort of other
1095db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // bug.
1096db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    assert(StartColNo <= EndColNo && "Trying to highlight whitespace??");
1097db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
1098db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
10996749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(StartColNo <= map.getSourceLine().size() && "Invalid range!");
11006749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(EndColNo <= map.getSourceLine().size() && "Invalid range!");
11016749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1102db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // Fill the range with ~'s.
11036749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  StartColNo = map.byteToColumn(StartColNo);
11046749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  EndColNo = map.byteToColumn(EndColNo);
11056749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
11066749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  assert(StartColNo <= EndColNo && "Invalid range!");
11076749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  if (CaretLine.size() < EndColNo)
11086749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell    CaretLine.resize(EndColNo,' ');
11096749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  std::fill(CaretLine.begin()+StartColNo,CaretLine.begin()+EndColNo,'~');
1110db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
1111db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
11126749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrellstd::string TextDiagnostic::buildFixItInsertionLine(
11136749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  unsigned LineNo,
11146749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  const SourceColumnMap &map,
111516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  ArrayRef<FixItHint> Hints,
111616afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis  const SourceManager &SM) {
11176749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
1118db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  std::string FixItInsertionLine;
1119db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (Hints.empty() || !DiagOpts.ShowFixits)
1120db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    return FixItInsertionLine;
1121bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose  unsigned PrevHintEndCol = 0;
1122db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1123db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
1124db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth       I != E; ++I) {
1125db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (!I->CodeToInsert.empty()) {
1126db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      // We have an insertion hint. Determine whether the inserted
1127bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose      // code contains no newlines and is on the same line as the caret.
1128db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      std::pair<FileID, unsigned> HintLocInfo
1129db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        = SM.getDecomposedExpansionLoc(I->RemoveRange.getBegin());
1130bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose      if (LineNo == SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) &&
1131bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose          StringRef(I->CodeToInsert).find_first_of("\n\r") == StringRef::npos) {
1132db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        // Insert the new code into the line just below the code
1133db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        // that the user wrote.
1134bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        // Note: When modifying this function, be very careful about what is a
1135bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        // "column" (printed width, platform-dependent) and what is a
1136bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        // "byte offset" (SourceManager "column").
1137bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        unsigned HintByteOffset
11386749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell          = SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second) - 1;
1139bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose
1140bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        // The hint must start inside the source or right at the end
1141bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        assert(HintByteOffset < static_cast<unsigned>(map.bytes())+1);
1142bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        unsigned HintCol = map.byteToColumn(HintByteOffset);
11436749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell
11443772c9abf9651da1f77c83ec937c96e10a353c6aJordan Rose        // If we inserted a long previous hint, push this one forwards, and add
11453772c9abf9651da1f77c83ec937c96e10a353c6aJordan Rose        // an extra space to show that this is not part of the previous
11463772c9abf9651da1f77c83ec937c96e10a353c6aJordan Rose        // completion. This is sort of the best we can do when two hints appear
11473772c9abf9651da1f77c83ec937c96e10a353c6aJordan Rose        // to overlap.
11483772c9abf9651da1f77c83ec937c96e10a353c6aJordan Rose        //
11493772c9abf9651da1f77c83ec937c96e10a353c6aJordan Rose        // Note that if this hint is located immediately after the previous
11503772c9abf9651da1f77c83ec937c96e10a353c6aJordan Rose        // hint, no space will be added, since the location is more important.
1151bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        if (HintCol < PrevHintEndCol)
1152bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose          HintCol = PrevHintEndCol + 1;
1153bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose
1154bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        // FIXME: This function handles multibyte characters in the source, but
1155bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        // not in the fixits. This assertion is intended to catch unintended
1156bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        // use of multibyte characters in fixits. If we decide to do this, we'll
1157bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        // have to track separate byte widths for the source and fixit lines.
1158bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        assert((size_t)llvm::sys::locale::columnWidth(I->CodeToInsert) ==
1159bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose               I->CodeToInsert.size());
1160bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose
1161bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        // This relies on one byte per column in our fixit hints.
1162bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        // This should NOT use HintByteOffset, because the source might have
1163bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        // Unicode characters in earlier columns.
1164bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        unsigned LastColumnModified = HintCol + I->CodeToInsert.size();
1165db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        if (LastColumnModified > FixItInsertionLine.size())
1166db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth          FixItInsertionLine.resize(LastColumnModified, ' ');
1167bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose
1168db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        std::copy(I->CodeToInsert.begin(), I->CodeToInsert.end(),
1169bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose                  FixItInsertionLine.begin() + HintCol);
11703772c9abf9651da1f77c83ec937c96e10a353c6aJordan Rose
1171bbe0175255d4da42cd99d93ca1e60c8eabcb4b9aJordan Rose        PrevHintEndCol = LastColumnModified;
1172db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      } else {
1173db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        FixItInsertionLine.clear();
1174db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        break;
1175db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      }
1176db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    }
1177db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
1178db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
11796749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell  expandTabs(FixItInsertionLine, DiagOpts.TabStop);
1180db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1181db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  return FixItInsertionLine;
1182db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
1183db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
118416afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidisvoid TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints,
118516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis                                         const SourceManager &SM) {
1186db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  if (!DiagOpts.ShowParseableFixits)
1187db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    return;
1188db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1189db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // We follow FixItRewriter's example in not (yet) handling
1190db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  // fix-its in macros.
1191db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
1192db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth       I != E; ++I) {
1193db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (I->RemoveRange.isInvalid() ||
1194db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        I->RemoveRange.getBegin().isMacroID() ||
1195db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth        I->RemoveRange.getEnd().isMacroID())
1196db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      return;
1197db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
1198db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1199db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end();
1200db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth       I != E; ++I) {
1201db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    SourceLocation BLoc = I->RemoveRange.getBegin();
1202db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    SourceLocation ELoc = I->RemoveRange.getEnd();
1203db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1204db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc);
1205db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc);
1206db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1207db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // Adjust for token ranges.
1208db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (I->RemoveRange.isTokenRange())
1209db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, LangOpts);
1210db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1211db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // We specifically do not do word-wrapping or tab-expansion here,
1212db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    // because this is supposed to be easy to parse.
1213db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    PresumedLoc PLoc = SM.getPresumedLoc(BLoc);
1214db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    if (PLoc.isInvalid())
1215db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      break;
1216db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth
1217db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS << "fix-it:\"";
1218db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS.write_escaped(PLoc.getFilename());
1219db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS << "\":{" << SM.getLineNumber(BInfo.first, BInfo.second)
1220db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      << ':' << SM.getColumnNumber(BInfo.first, BInfo.second)
1221db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      << '-' << SM.getLineNumber(EInfo.first, EInfo.second)
1222db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      << ':' << SM.getColumnNumber(EInfo.first, EInfo.second)
1223db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth      << "}:\"";
1224db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS.write_escaped(I->CodeToInsert);
1225db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth    OS << "\"\n";
1226db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth  }
1227db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth}
1228