1db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth//===--- TextDiagnostic.cpp - Text Diagnostic Pretty-Printing -------------===// 2db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth// 3db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth// The LLVM Compiler Infrastructure 4db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth// 5db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth// This file is distributed under the University of Illinois Open Source 6db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth// License. See LICENSE.TXT for details. 7db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth// 8db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth//===----------------------------------------------------------------------===// 9db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 10db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth#include "clang/Frontend/TextDiagnostic.h" 113f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose#include "clang/Basic/CharInfo.h" 1202c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor#include "clang/Basic/DiagnosticOptions.h" 1355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/FileManager.h" 1455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/SourceManager.h" 15db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth#include "clang/Lex/Lexer.h" 16db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth#include "llvm/ADT/SmallString.h" 176749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell#include "llvm/ADT/StringExtras.h" 18cb5620c9b213f4bd323912159fdddda35e258a14Dmitri Gribenko#include "llvm/Support/ConvertUTF.h" 1955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/ErrorHandling.h" 2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/Locale.h" 2155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/MemoryBuffer.h" 2255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/Support/raw_ostream.h" 23db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth#include <algorithm> 246749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 25db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthusing namespace clang; 26db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 27db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic const enum raw_ostream::Colors noteColor = 28db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth raw_ostream::BLACK; 29651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic const enum raw_ostream::Colors remarkColor = 30651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines raw_ostream::BLUE; 31db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic const enum raw_ostream::Colors fixitColor = 32db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth raw_ostream::GREEN; 33db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic const enum raw_ostream::Colors caretColor = 34db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth raw_ostream::GREEN; 35db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic const enum raw_ostream::Colors warningColor = 36db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth raw_ostream::MAGENTA; 37246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieustatic const enum raw_ostream::Colors templateColor = 38246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu raw_ostream::CYAN; 39db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic const enum raw_ostream::Colors errorColor = raw_ostream::RED; 40db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic const enum raw_ostream::Colors fatalColor = raw_ostream::RED; 41db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth// Used for changing only the bold attribute. 42db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic const enum raw_ostream::Colors savedColor = 43db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth raw_ostream::SAVEDCOLOR; 44db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 45246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu/// \brief Add highlights to differences in template strings. 46246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieustatic void applyTemplateHighlighting(raw_ostream &OS, StringRef Str, 47b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu bool &Normal, bool Bold) { 484ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer while (1) { 494ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer size_t Pos = Str.find(ToggleHighlight); 504ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer OS << Str.slice(0, Pos); 514ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer if (Pos == StringRef::npos) 524ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer break; 534ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer 544ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer Str = Str.substr(Pos + 1); 554ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer if (Normal) 564ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer OS.changeColor(templateColor, true); 574ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer else { 584ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer OS.resetColor(); 594ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer if (Bold) 604ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer OS.changeColor(savedColor, true); 61246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu } 624ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer Normal = !Normal; 634ca3abd3680afec6207d25d0bb80838bf59ecbfeBenjamin Kramer } 64246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu} 65246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu 66db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief Number of spaces to indent when word-wrapping. 67db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthconst unsigned WordWrapIndentation = 6; 68db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 69d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramerstatic int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i) { 706749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell int bytes = 0; 716749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell while (0<i) { 726749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (SourceLine[--i]=='\t') 736749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell break; 746749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell ++bytes; 756749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell } 766749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell return bytes; 776749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell} 786749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 796749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// \brief returns a printable representation of first item from input range 806749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// 816749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// This function returns a printable representation of the next item in a line 826749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// of source. If the next byte begins a valid and printable character, that 836749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// character is returned along with 'true'. 846749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// 856749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// Otherwise, if the next byte begins a valid, but unprintable character, a 866749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// printable, escaped representation of the character is returned, along with 876749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// 'false'. Otherwise a printable, escaped representation of the next byte 886749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// is returned along with 'false'. 896749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// 906749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// \note The index is updated to be used with a subsequent call to 916749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// printableTextForNextCharacter. 926749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// 936749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// \param SourceLine The line of source 946749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// \param i Pointer to byte index, 956749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// \param TabStop used to expand tabs 96f3477c13eeaf11b32a41f181398fb5deffd0dd73Sylvestre Ledru/// \return pair(printable text, 'true' iff original text was printable) 976749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// 98d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramerstatic std::pair<SmallString<16>, bool> 996749dd50869281f9b49ad5960e25288c15a71cacSeth CantrellprintableTextForNextCharacter(StringRef SourceLine, size_t *i, 1006749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell unsigned TabStop) { 1016749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell assert(i && "i must not be null"); 1026749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell assert(*i<SourceLine.size() && "must point to a valid index"); 1036749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 1046749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (SourceLine[*i]=='\t') { 1056749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop && 1066749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell "Invalid -ftabstop value"); 1076749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell unsigned col = bytesSincePreviousTabOrLineBegin(SourceLine, *i); 1086749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell unsigned NumSpaces = TabStop - col%TabStop; 1096749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell assert(0 < NumSpaces && NumSpaces <= TabStop 1106749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell && "Invalid computation of space amt"); 1116749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell ++(*i); 1126749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 1136749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell SmallString<16> expandedTab; 1146749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell expandedTab.assign(NumSpaces, ' '); 1156749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell return std::make_pair(expandedTab, true); 1166749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell } 1176749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 1186749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell unsigned char const *begin, *end; 1196749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell begin = reinterpret_cast<unsigned char const *>(&*(SourceLine.begin() + *i)); 120c6a2f6e2dd16368f4a60178b5e20b63fcafb5481Seth Cantrell end = begin + (SourceLine.size() - *i); 1216749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 1226749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (isLegalUTF8Sequence(begin, end)) { 1236749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell UTF32 c; 1246749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell UTF32 *cptr = &c; 1256749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell unsigned char const *original_begin = begin; 1260d1e645bbfd3727b0dd758bdb685c6e5c7592fecSeth Cantrell unsigned char const *cp_end = begin+getNumBytesForUTF8(SourceLine[*i]); 1276749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 1286749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell ConversionResult res = ConvertUTF8toUTF32(&begin, cp_end, &cptr, cptr+1, 1296749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell strictConversion); 1300ddb097bb02ddee8f1924ee4fcca384cb18ad8c5Matt Beaumont-Gay (void)res; 1316749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell assert(conversionOK==res); 1326749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell assert(0 < begin-original_begin 1336749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell && "we must be further along in the string now"); 1346749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell *i += begin-original_begin; 1356749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 1366749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (!llvm::sys::locale::isPrint(c)) { 1376749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell // If next character is valid UTF-8, but not printable 1386749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell SmallString<16> expandedCP("<U+>"); 1396749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell while (c) { 1406749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(c%16)); 1416749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell c/=16; 1426749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell } 1436749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell while (expandedCP.size() < 8) 1446749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(0)); 1456749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell return std::make_pair(expandedCP, false); 1466749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell } 1476749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 1486749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell // If next character is valid UTF-8, and printable 1496749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell return std::make_pair(SmallString<16>(original_begin, cp_end), true); 1506749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 1516749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell } 1526749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 1536749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell // If next byte is not valid UTF-8 (and therefore not printable) 1546749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell SmallString<16> expandedByte("<XX>"); 1556749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell unsigned char byte = SourceLine[*i]; 1566749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell expandedByte[1] = llvm::hexdigit(byte / 16); 1576749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell expandedByte[2] = llvm::hexdigit(byte % 16); 1586749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell ++(*i); 1596749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell return std::make_pair(expandedByte, false); 1606749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell} 1616749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 162d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramerstatic void expandTabs(std::string &SourceLine, unsigned TabStop) { 1636749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell size_t i = SourceLine.size(); 1646749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell while (i>0) { 1656749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell i--; 1666749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (SourceLine[i]!='\t') 1676749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell continue; 1686749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell size_t tmp_i = i; 1696749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell std::pair<SmallString<16>,bool> res 1706749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell = printableTextForNextCharacter(SourceLine, &tmp_i, TabStop); 1716749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell SourceLine.replace(i, 1, res.first.c_str()); 1726749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell } 1736749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell} 1746749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 1756749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// This function takes a raw source line and produces a mapping from the bytes 1766749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// of the printable representation of the line to the columns those printable 1776749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// characters will appear at (numbering the first column as 0). 1786749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// 1796749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// If a byte 'i' corresponds to muliple columns (e.g. the byte contains a tab 180bed28ac1d1463adca3ecf24fca5c30646fa9dbb2Sylvestre Ledru/// character) then the array will map that byte to the first column the 1816749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// tab appears at and the next value in the map will have been incremented 1826749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// more than once. 1836749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// 1846749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// If a byte is the first in a sequence of bytes that together map to a single 1856749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// entity in the output, then the array will map that byte to the appropriate 1866749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// column while the subsequent bytes will be -1. 1876749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// 1886749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// The last element in the array does not correspond to any byte in the input 1896749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// and instead is the number of columns needed to display the source 1906749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// 1916749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// example: (given a tabstop of 8) 1926749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// 1936749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// "a \t \u3042" -> {0,1,2,8,9,-1,-1,11} 1946749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// 1956b4f50662a1857d5203254fb2c52975e6f30fc90James Dennett/// (\\u3042 is represented in UTF-8 by three bytes and takes two columns to 1966749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// display) 197d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramerstatic void byteToColumn(StringRef SourceLine, unsigned TabStop, 198d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramer SmallVectorImpl<int> &out) { 1996749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell out.clear(); 2006749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 2016749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (SourceLine.empty()) { 2026749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell out.resize(1u,0); 2036749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell return; 2046749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell } 2056749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 2066749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell out.resize(SourceLine.size()+1, -1); 2076749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 2086749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell int columns = 0; 2096749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell size_t i = 0; 2106749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell while (i<SourceLine.size()) { 2116749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell out[i] = columns; 2126749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell std::pair<SmallString<16>,bool> res 2136749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell = printableTextForNextCharacter(SourceLine, &i, TabStop); 2146749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell columns += llvm::sys::locale::columnWidth(res.first); 2156749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell } 2166749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell out.back() = columns; 2176749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell} 2186749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 2196749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// This function takes a raw source line and produces a mapping from columns 2206749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// to the byte of the source line that produced the character displaying at 2216749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// that column. This is the inverse of the mapping produced by byteToColumn() 2226749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// 2236749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// The last element in the array is the number of bytes in the source string 2246749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// 2256749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// example: (given a tabstop of 8) 2266749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// 2276749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// "a \t \u3042" -> {0,1,2,-1,-1,-1,-1,-1,3,4,-1,7} 2286749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// 2296b4f50662a1857d5203254fb2c52975e6f30fc90James Dennett/// (\\u3042 is represented in UTF-8 by three bytes and takes two columns to 2306749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell/// display) 231d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramerstatic void columnToByte(StringRef SourceLine, unsigned TabStop, 2326749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell SmallVectorImpl<int> &out) { 2336749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell out.clear(); 2346749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 2356749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (SourceLine.empty()) { 2366749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell out.resize(1u, 0); 2376749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell return; 2386749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell } 2396749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 2406749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell int columns = 0; 2416749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell size_t i = 0; 2426749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell while (i<SourceLine.size()) { 2436749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell out.resize(columns+1, -1); 2446749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell out.back() = i; 2456749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell std::pair<SmallString<16>,bool> res 2466749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell = printableTextForNextCharacter(SourceLine, &i, TabStop); 2476749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell columns += llvm::sys::locale::columnWidth(res.first); 2486749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell } 2496749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell out.resize(columns+1, -1); 2506749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell out.back() = i; 2516749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell} 2526749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 253c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramernamespace { 2546749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrellstruct SourceColumnMap { 2556749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell SourceColumnMap(StringRef SourceLine, unsigned TabStop) 2566749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell : m_SourceLine(SourceLine) { 2576749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 2586749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell ::byteToColumn(SourceLine, TabStop, m_byteToColumn); 2596749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell ::columnToByte(SourceLine, TabStop, m_columnToByte); 2606749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 2616749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell assert(m_byteToColumn.size()==SourceLine.size()+1); 2626749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell assert(0 < m_byteToColumn.size() && 0 < m_columnToByte.size()); 2636749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell assert(m_byteToColumn.size() 2646749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell == static_cast<unsigned>(m_columnToByte.back()+1)); 2656749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell assert(static_cast<unsigned>(m_byteToColumn.back()+1) 2666749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell == m_columnToByte.size()); 2676749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell } 2686749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell int columns() const { return m_byteToColumn.back(); } 2696749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell int bytes() const { return m_columnToByte.back(); } 270c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith 271c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith /// \brief Map a byte to the column which it is at the start of, or return -1 272c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith /// if it is not at the start of a column (for a UTF-8 trailing byte). 2736749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell int byteToColumn(int n) const { 2746749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell assert(0<=n && n<static_cast<int>(m_byteToColumn.size())); 2756749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell return m_byteToColumn[n]; 2766749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell } 277c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith 278c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith /// \brief Map a byte to the first column which contains it. 279c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith int byteToContainingColumn(int N) const { 280c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith assert(0 <= N && N < static_cast<int>(m_byteToColumn.size())); 281c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith while (m_byteToColumn[N] == -1) 282c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith --N; 283c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith return m_byteToColumn[N]; 284c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith } 285c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith 286c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith /// \brief Map a column to the byte which starts the column, or return -1 if 287c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith /// the column the second or subsequent column of an expanded tab or similar 288c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith /// multi-column entity. 2896749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell int columnToByte(int n) const { 2906749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell assert(0<=n && n<static_cast<int>(m_columnToByte.size())); 2916749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell return m_columnToByte[n]; 2926749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell } 293c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith 294c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith /// \brief Map from a byte index to the next byte which starts a column. 295c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith int startOfNextColumn(int N) const { 296c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith assert(0 <= N && N < static_cast<int>(m_columnToByte.size() - 1)); 297c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith while (byteToColumn(++N) == -1) {} 298c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith return N; 299c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith } 300c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith 301c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith /// \brief Map from a byte index to the previous byte which starts a column. 302c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith int startOfPreviousColumn(int N) const { 303c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith assert(0 < N && N < static_cast<int>(m_columnToByte.size())); 304eaa5a2b5e099bf29856bc88b03cd7c9d473f671dSeth Cantrell while (byteToColumn(--N) == -1) {} 305c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith return N; 306c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith } 307c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith 3086749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell StringRef getSourceLine() const { 3096749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell return m_SourceLine; 3106749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell } 3116749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 3126749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrellprivate: 3136749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell const std::string m_SourceLine; 3146749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell SmallVector<int,200> m_byteToColumn; 3156749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell SmallVector<int,200> m_columnToByte; 3166749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell}; 317c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer} // end anonymous namespace 3186749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 319db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief When the source code line we want to print is too long for 320db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// the terminal, select the "interesting" region. 3217531f571808201d44002fa38b67ee0a81e5ae936Chandler Carruthstatic void selectInterestingSourceRegion(std::string &SourceLine, 322db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth std::string &CaretLine, 323db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth std::string &FixItInsertionLine, 3246749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell unsigned Columns, 3256749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell const SourceColumnMap &map) { 3266749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell unsigned MaxColumns = std::max<unsigned>(map.columns(), 3276749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell std::max(CaretLine.size(), 3286749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell FixItInsertionLine.size())); 3296749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell // if the number of columns is less than the desired number we're done 3306749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (MaxColumns <= Columns) 3316749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell return; 3326749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 3331f13fbd0c5bac045aa7d6ae3e998758e9dfa3ce4Jordan Rose // No special characters are allowed in CaretLine. 3346749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell assert(CaretLine.end() == 3356749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell std::find_if(CaretLine.begin(), CaretLine.end(), 336651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines [](char c) { return c < ' ' || '~' < c; })); 3376749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 338db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Find the slice that we need to display the full caret line 339db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // correctly. 340db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth unsigned CaretStart = 0, CaretEnd = CaretLine.size(); 341db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth for (; CaretStart != CaretEnd; ++CaretStart) 3423f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose if (!isWhitespace(CaretLine[CaretStart])) 343db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth break; 344db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 345db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth for (; CaretEnd != CaretStart; --CaretEnd) 3463f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose if (!isWhitespace(CaretLine[CaretEnd - 1])) 347db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth break; 348db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 3496749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell // caret has already been inserted into CaretLine so the above whitespace 3506749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell // check is guaranteed to include the caret 351db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 352db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // If we have a fix-it line, make sure the slice includes all of the 353db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // fix-it information. 354db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth if (!FixItInsertionLine.empty()) { 355db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth unsigned FixItStart = 0, FixItEnd = FixItInsertionLine.size(); 356db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth for (; FixItStart != FixItEnd; ++FixItStart) 3573f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose if (!isWhitespace(FixItInsertionLine[FixItStart])) 358db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth break; 359db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 360db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth for (; FixItEnd != FixItStart; --FixItEnd) 3613f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose if (!isWhitespace(FixItInsertionLine[FixItEnd - 1])) 362db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth break; 363db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 3641f13fbd0c5bac045aa7d6ae3e998758e9dfa3ce4Jordan Rose // We can safely use the byte offset FixItStart as the column offset 3651f13fbd0c5bac045aa7d6ae3e998758e9dfa3ce4Jordan Rose // because the characters up until FixItStart are all ASCII whitespace 3661f13fbd0c5bac045aa7d6ae3e998758e9dfa3ce4Jordan Rose // characters. 3671f13fbd0c5bac045aa7d6ae3e998758e9dfa3ce4Jordan Rose unsigned FixItStartCol = FixItStart; 3681f13fbd0c5bac045aa7d6ae3e998758e9dfa3ce4Jordan Rose unsigned FixItEndCol 3691f13fbd0c5bac045aa7d6ae3e998758e9dfa3ce4Jordan Rose = llvm::sys::locale::columnWidth(FixItInsertionLine.substr(0, FixItEnd)); 3701f13fbd0c5bac045aa7d6ae3e998758e9dfa3ce4Jordan Rose 3711f13fbd0c5bac045aa7d6ae3e998758e9dfa3ce4Jordan Rose CaretStart = std::min(FixItStartCol, CaretStart); 3721f13fbd0c5bac045aa7d6ae3e998758e9dfa3ce4Jordan Rose CaretEnd = std::max(FixItEndCol, CaretEnd); 373db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth } 374db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 375c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell // CaretEnd may have been set at the middle of a character 376c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell // If it's not at a character's first column then advance it past the current 377c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell // character. 378c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell while (static_cast<int>(CaretEnd) < map.columns() && 379c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell -1 == map.columnToByte(CaretEnd)) 380c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell ++CaretEnd; 381c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell 382c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell assert((static_cast<int>(CaretStart) > map.columns() || 383c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell -1!=map.columnToByte(CaretStart)) && 384c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell "CaretStart must not point to a column in the middle of a source" 385c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell " line character"); 386c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell assert((static_cast<int>(CaretEnd) > map.columns() || 387c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell -1!=map.columnToByte(CaretEnd)) && 388c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell "CaretEnd must not point to a column in the middle of a source line" 389c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell " character"); 390c5493d7d60005fc8aa9b0e06d326026a9f9a688dSeth Cantrell 391db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // CaretLine[CaretStart, CaretEnd) contains all of the interesting 392db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // parts of the caret line. While this slice is smaller than the 393db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // number of columns we have, try to grow the slice to encompass 394db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // more context. 395db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 3966749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell unsigned SourceStart = map.columnToByte(std::min<unsigned>(CaretStart, 3976749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell map.columns())); 3986749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell unsigned SourceEnd = map.columnToByte(std::min<unsigned>(CaretEnd, 3996749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell map.columns())); 4006749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 4016749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell unsigned CaretColumnsOutsideSource = CaretEnd-CaretStart 4026749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell - (map.byteToColumn(SourceEnd)-map.byteToColumn(SourceStart)); 4036749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 4046749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell char const *front_ellipse = " ..."; 4056749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell char const *front_space = " "; 4066749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell char const *back_ellipse = "..."; 4076749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell unsigned ellipses_space = strlen(front_ellipse) + strlen(back_ellipse); 408db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 409db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth unsigned TargetColumns = Columns; 4106749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell // Give us extra room for the ellipses 4116749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell // and any of the caret line that extends past the source 4126749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (TargetColumns > ellipses_space+CaretColumnsOutsideSource) 4136749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell TargetColumns -= ellipses_space+CaretColumnsOutsideSource; 4146749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 4156749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell while (SourceStart>0 || SourceEnd<SourceLine.size()) { 416db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth bool ExpandedRegion = false; 4176749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 4186749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (SourceStart>0) { 4199cffb4a9ae548245ede15850cb96dfedf56255feSeth Cantrell unsigned NewStart = map.startOfPreviousColumn(SourceStart); 420db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 421db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Skip over any whitespace we see here; we're looking for 422db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // another bit of interesting text. 423c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith // FIXME: Detect non-ASCII whitespace characters too. 4243f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose while (NewStart && isWhitespace(SourceLine[NewStart])) 425c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith NewStart = map.startOfPreviousColumn(NewStart); 426db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 427db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Skip over this bit of "interesting" text. 428c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith while (NewStart) { 429c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith unsigned Prev = map.startOfPreviousColumn(NewStart); 4303f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose if (isWhitespace(SourceLine[Prev])) 431c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith break; 432c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith NewStart = Prev; 433c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith } 434db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 435c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith assert(map.byteToColumn(NewStart) != -1); 4366749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell unsigned NewColumns = map.byteToColumn(SourceEnd) - 4376749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell map.byteToColumn(NewStart); 4386749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (NewColumns <= TargetColumns) { 4396749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell SourceStart = NewStart; 440db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth ExpandedRegion = true; 441db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth } 442db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth } 443db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 4446749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (SourceEnd<SourceLine.size()) { 4459cffb4a9ae548245ede15850cb96dfedf56255feSeth Cantrell unsigned NewEnd = map.startOfNextColumn(SourceEnd); 446db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 447db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Skip over any whitespace we see here; we're looking for 448db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // another bit of interesting text. 449c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith // FIXME: Detect non-ASCII whitespace characters too. 4503f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose while (NewEnd < SourceLine.size() && isWhitespace(SourceLine[NewEnd])) 451c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith NewEnd = map.startOfNextColumn(NewEnd); 452db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 453db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Skip over this bit of "interesting" text. 4543f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose while (NewEnd < SourceLine.size() && isWhitespace(SourceLine[NewEnd])) 455c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith NewEnd = map.startOfNextColumn(NewEnd); 456db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 457c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith assert(map.byteToColumn(NewEnd) != -1); 4586749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell unsigned NewColumns = map.byteToColumn(NewEnd) - 4596749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell map.byteToColumn(SourceStart); 4606749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (NewColumns <= TargetColumns) { 4616749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell SourceEnd = NewEnd; 462db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth ExpandedRegion = true; 463db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth } 464db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth } 465db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 466db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth if (!ExpandedRegion) 467db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth break; 468db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth } 469db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 4706749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell CaretStart = map.byteToColumn(SourceStart); 4716749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell CaretEnd = map.byteToColumn(SourceEnd) + CaretColumnsOutsideSource; 4726749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 473db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // [CaretStart, CaretEnd) is the slice we want. Update the various 474db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // output lines to show only this slice, with two-space padding 475db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // before the lines so that it looks nicer. 4766749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 4776749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell assert(CaretStart!=(unsigned)-1 && CaretEnd!=(unsigned)-1 && 4786749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell SourceStart!=(unsigned)-1 && SourceEnd!=(unsigned)-1); 4796749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell assert(SourceStart <= SourceEnd); 4806749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell assert(CaretStart <= CaretEnd); 4816749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 4826749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell unsigned BackColumnsRemoved 4836749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell = map.byteToColumn(SourceLine.size())-map.byteToColumn(SourceEnd); 4846749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell unsigned FrontColumnsRemoved = CaretStart; 4856749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell unsigned ColumnsKept = CaretEnd-CaretStart; 4866749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 4876749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell // We checked up front that the line needed truncation 4886749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell assert(FrontColumnsRemoved+ColumnsKept+BackColumnsRemoved > Columns); 4896749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 4906749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell // The line needs some trunctiona, and we'd prefer to keep the front 4916749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell // if possible, so remove the back 492191db6dc0d6290b5f2993691e409ff2dc8b4345eSeth Cantrell if (BackColumnsRemoved > strlen(back_ellipse)) 4936749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell SourceLine.replace(SourceEnd, std::string::npos, back_ellipse); 4946749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 4956749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell // If that's enough then we're done 4966749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (FrontColumnsRemoved+ColumnsKept <= Columns) 4976749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell return; 4986749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 4996749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell // Otherwise remove the front as well 500191db6dc0d6290b5f2993691e409ff2dc8b4345eSeth Cantrell if (FrontColumnsRemoved > strlen(front_ellipse)) { 5016749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell SourceLine.replace(0, SourceStart, front_ellipse); 5026749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell CaretLine.replace(0, CaretStart, front_space); 5036749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (!FixItInsertionLine.empty()) 5046749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell FixItInsertionLine.replace(0, CaretStart, front_space); 505db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth } 506db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth} 507db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 508db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief Skip over whitespace in the string, starting at the given 509db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// index. 510db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// 511db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \returns The index of the first non-whitespace character that is 512db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// greater than or equal to Idx or, if no such character exists, 513db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// returns the end of the string. 514db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic unsigned skipWhitespace(unsigned Idx, StringRef Str, unsigned Length) { 5153f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose while (Idx < Length && isWhitespace(Str[Idx])) 516db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth ++Idx; 517db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth return Idx; 518db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth} 519db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 520db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief If the given character is the start of some kind of 521db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// balanced punctuation (e.g., quotes or parentheses), return the 522db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// character that will terminate the punctuation. 523db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// 524db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \returns The ending punctuation character, if any, or the NULL 525db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// character if the input character does not start any punctuation. 526db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic inline char findMatchingPunctuation(char c) { 527db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth switch (c) { 528db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth case '\'': return '\''; 529db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth case '`': return '\''; 530db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth case '"': return '"'; 531db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth case '(': return ')'; 532db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth case '[': return ']'; 533db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth case '{': return '}'; 534db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth default: break; 535db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth } 536db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 537db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth return 0; 538db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth} 539db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 540db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief Find the end of the word starting at the given offset 541db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// within a string. 542db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// 543db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \returns the index pointing one character past the end of the 544db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// word. 545db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic unsigned findEndOfWord(unsigned Start, StringRef Str, 546db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth unsigned Length, unsigned Column, 547db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth unsigned Columns) { 548db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth assert(Start < Str.size() && "Invalid start position!"); 549db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth unsigned End = Start + 1; 550db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 551db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // If we are already at the end of the string, take that as the word. 552db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth if (End == Str.size()) 553db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth return End; 554db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 555db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Determine if the start of the string is actually opening 556db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // punctuation, e.g., a quote or parentheses. 557db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth char EndPunct = findMatchingPunctuation(Str[Start]); 558db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth if (!EndPunct) { 559db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // This is a normal word. Just find the first space character. 5603f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose while (End < Length && !isWhitespace(Str[End])) 561db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth ++End; 562db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth return End; 563db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth } 564db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 565db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // We have the start of a balanced punctuation sequence (quotes, 566db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // parentheses, etc.). Determine the full sequence is. 567f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<16> PunctuationEndStack; 568db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth PunctuationEndStack.push_back(EndPunct); 569db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth while (End < Length && !PunctuationEndStack.empty()) { 570db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth if (Str[End] == PunctuationEndStack.back()) 571db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth PunctuationEndStack.pop_back(); 572db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth else if (char SubEndPunct = findMatchingPunctuation(Str[End])) 573db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth PunctuationEndStack.push_back(SubEndPunct); 574db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 575db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth ++End; 576db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth } 577db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 578db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Find the first space character after the punctuation ended. 5793f6f51e28231f65de9c2dd150a2d757b2162cfa3Jordan Rose while (End < Length && !isWhitespace(Str[End])) 580db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth ++End; 581db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 582db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth unsigned PunctWordLength = End - Start; 583db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth if (// If the word fits on this line 584db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth Column + PunctWordLength <= Columns || 585db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // ... or the word is "short enough" to take up the next line 586db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // without too much ugly white space 587db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth PunctWordLength < Columns/3) 588db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth return End; // Take the whole thing as a single "word". 589db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 590db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // The whole quoted/parenthesized string is too long to print as a 591db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // single "word". Instead, find the "word" that starts just after 592db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // the punctuation and use that end-point instead. This will recurse 593db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // until it finds something small enough to consider a word. 594db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth return findEndOfWord(Start + 1, Str, Length, Column + 1, Columns); 595db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth} 596db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 597db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief Print the given string to a stream, word-wrapping it to 598db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// some number of columns in the process. 599db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// 600db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param OS the stream to which the word-wrapping string will be 601db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// emitted. 602db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Str the string to word-wrap and output. 603db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Columns the number of columns to word-wrap to. 604db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Column the column number at which the first character of \p 605db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// Str will be printed. This will be non-zero when part of the first 606db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// line has already been printed. 607b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu/// \param Bold if the current text should be bold 608db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Indentation the number of spaces to indent any lines beyond 609db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// the first line. 610db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \returns true if word-wrapping was required, or false if the 611db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// string fit on the first line. 612db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruthstatic bool printWordWrapped(raw_ostream &OS, StringRef Str, 613db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth unsigned Columns, 614db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth unsigned Column = 0, 615b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu bool Bold = false, 616db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth unsigned Indentation = WordWrapIndentation) { 617db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth const unsigned Length = std::min(Str.find('\n'), Str.size()); 618246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu bool TextNormal = true; 619db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 620db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // The string used to indent each line. 621f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<16> IndentStr; 622db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth IndentStr.assign(Indentation, ' '); 623db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth bool Wrapped = false; 624db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth for (unsigned WordStart = 0, WordEnd; WordStart < Length; 625db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth WordStart = WordEnd) { 626db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Find the beginning of the next word. 627db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth WordStart = skipWhitespace(WordStart, Str, Length); 628db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth if (WordStart == Length) 629db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth break; 630db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 631db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Find the end of this word. 632db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth WordEnd = findEndOfWord(WordStart, Str, Length, Column, Columns); 633db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 634db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Does this word fit on the current line? 635db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth unsigned WordLength = WordEnd - WordStart; 636db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth if (Column + WordLength < Columns) { 637db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // This word fits on the current line; print it there. 638db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth if (WordStart) { 639db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth OS << ' '; 640db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth Column += 1; 641db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth } 642246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength), 643b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu TextNormal, Bold); 644db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth Column += WordLength; 645db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth continue; 646db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth } 647db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 648db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // This word does not fit on the current line, so wrap to the next 649db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // line. 650db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth OS << '\n'; 651db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth OS.write(&IndentStr[0], Indentation); 652246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength), 653b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu TextNormal, Bold); 654db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth Column = Indentation + WordLength; 655db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth Wrapped = true; 656db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth } 657db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 658db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Append any remaning text from the message with its existing formatting. 659b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu applyTemplateHighlighting(OS, Str.substr(Length), TextNormal, Bold); 660246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu 661246b6aa6763de8c617d564ef33123a8f3293a80eRichard Trieu assert(TextNormal && "Text highlighted at end of diagnostic message."); 662db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 663db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth return Wrapped; 664db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth} 665db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 666db463bb2e4a9751f4cbe53996db751e1985ee966Chandler CarruthTextDiagnostic::TextDiagnostic(raw_ostream &OS, 667db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth const LangOptions &LangOpts, 66802c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor DiagnosticOptions *DiagOpts) 66916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis : DiagnosticRenderer(LangOpts, DiagOpts), OS(OS) {} 670db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 6712898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted KremenekTextDiagnostic::~TextDiagnostic() {} 672db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 6732898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid 6742898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted KremenekTextDiagnostic::emitDiagnosticMessage(SourceLocation Loc, 6752898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek PresumedLoc PLoc, 6762898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek DiagnosticsEngine::Level Level, 6772898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek StringRef Message, 6782898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek ArrayRef<clang::CharSourceRange> Ranges, 67916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager *SM, 6808be51eab5ad34515d2a40dcdc8558128ca1800adTed Kremenek DiagOrStoredDiag D) { 681db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth uint64_t StartOfLocationInfo = OS.tell(); 682db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 6832898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek // Emit the location of this particular diagnostic. 68416afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis if (Loc.isValid()) 68516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitDiagnosticLoc(Loc, PLoc, Level, Ranges, *SM); 6862898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 68702c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (DiagOpts->ShowColors) 688db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth OS.resetColor(); 6892898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek 69089e32745123c02159fa1d1f19f96bdd4173029f0Hans Wennborg printDiagnosticLevel(OS, Level, DiagOpts->ShowColors, 69189e32745123c02159fa1d1f19f96bdd4173029f0Hans Wennborg DiagOpts->CLFallbackMode); 692ef8225444452a1486bd721f3285301fe84643b00Stephen Hines printDiagnosticMessage(OS, 693ef8225444452a1486bd721f3285301fe84643b00Stephen Hines /*IsSupplemental*/ Level == DiagnosticsEngine::Note, 694ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Message, OS.tell() - StartOfLocationInfo, 69502c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor DiagOpts->MessageLength, DiagOpts->ShowColors); 696db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth} 697db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 6986ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/*static*/ void 6996ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler CarruthTextDiagnostic::printDiagnosticLevel(raw_ostream &OS, 7006ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth DiagnosticsEngine::Level Level, 70189e32745123c02159fa1d1f19f96bdd4173029f0Hans Wennborg bool ShowColors, 70289e32745123c02159fa1d1f19f96bdd4173029f0Hans Wennborg bool CLFallbackMode) { 7036ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth if (ShowColors) { 7046ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth // Print diagnostic category in bold and color 7056ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth switch (Level) { 7066ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth case DiagnosticsEngine::Ignored: 7076ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth llvm_unreachable("Invalid diagnostic type"); 7086ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth case DiagnosticsEngine::Note: OS.changeColor(noteColor, true); break; 709651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case DiagnosticsEngine::Remark: OS.changeColor(remarkColor, true); break; 7106ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth case DiagnosticsEngine::Warning: OS.changeColor(warningColor, true); break; 7116ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth case DiagnosticsEngine::Error: OS.changeColor(errorColor, true); break; 7126ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth case DiagnosticsEngine::Fatal: OS.changeColor(fatalColor, true); break; 7136ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth } 7146ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth } 7156ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 7166ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth switch (Level) { 7176ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth case DiagnosticsEngine::Ignored: 7186ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth llvm_unreachable("Invalid diagnostic type"); 71989e32745123c02159fa1d1f19f96bdd4173029f0Hans Wennborg case DiagnosticsEngine::Note: OS << "note"; break; 720651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines case DiagnosticsEngine::Remark: OS << "remark"; break; 72189e32745123c02159fa1d1f19f96bdd4173029f0Hans Wennborg case DiagnosticsEngine::Warning: OS << "warning"; break; 72289e32745123c02159fa1d1f19f96bdd4173029f0Hans Wennborg case DiagnosticsEngine::Error: OS << "error"; break; 72389e32745123c02159fa1d1f19f96bdd4173029f0Hans Wennborg case DiagnosticsEngine::Fatal: OS << "fatal error"; break; 7246ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth } 7256ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 72689e32745123c02159fa1d1f19f96bdd4173029f0Hans Wennborg // In clang-cl /fallback mode, print diagnostics as "error(clang):". This 72789e32745123c02159fa1d1f19f96bdd4173029f0Hans Wennborg // makes it more clear whether a message is coming from clang or cl.exe, 72889e32745123c02159fa1d1f19f96bdd4173029f0Hans Wennborg // and it prevents MSBuild from concluding that the build failed just because 72989e32745123c02159fa1d1f19f96bdd4173029f0Hans Wennborg // there is an "error:" in the output. 73089e32745123c02159fa1d1f19f96bdd4173029f0Hans Wennborg if (CLFallbackMode) 73189e32745123c02159fa1d1f19f96bdd4173029f0Hans Wennborg OS << "(clang)"; 73289e32745123c02159fa1d1f19f96bdd4173029f0Hans Wennborg 73389e32745123c02159fa1d1f19f96bdd4173029f0Hans Wennborg OS << ": "; 73489e32745123c02159fa1d1f19f96bdd4173029f0Hans Wennborg 7356ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth if (ShowColors) 7366ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth OS.resetColor(); 7376ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth} 7386ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 739ef8225444452a1486bd721f3285301fe84643b00Stephen Hines/*static*/ 740ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesvoid TextDiagnostic::printDiagnosticMessage(raw_ostream &OS, 741ef8225444452a1486bd721f3285301fe84643b00Stephen Hines bool IsSupplemental, 742ef8225444452a1486bd721f3285301fe84643b00Stephen Hines StringRef Message, 743ef8225444452a1486bd721f3285301fe84643b00Stephen Hines unsigned CurrentColumn, 744ef8225444452a1486bd721f3285301fe84643b00Stephen Hines unsigned Columns, bool ShowColors) { 745b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu bool Bold = false; 746ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (ShowColors && !IsSupplemental) { 747ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // Print primary diagnostic messages in bold and without color, to visually 748ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // indicate the transition from continuation notes and other output. 749ef8225444452a1486bd721f3285301fe84643b00Stephen Hines OS.changeColor(savedColor, true); 750ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Bold = true; 7516ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth } 7526ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 7536ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth if (Columns) 754b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu printWordWrapped(OS, Message, Columns, CurrentColumn, Bold); 75550badd523b9b90c0731423d002b13a00bf754036David Blaikie else { 75650badd523b9b90c0731423d002b13a00bf754036David Blaikie bool Normal = true; 757b956e5a2439bce94ba2e1da264471859632eb11fRichard Trieu applyTemplateHighlighting(OS, Message, Normal, Bold); 75850badd523b9b90c0731423d002b13a00bf754036David Blaikie assert(Normal && "Formatting should have returned to normal"); 75950badd523b9b90c0731423d002b13a00bf754036David Blaikie } 7606ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 7616ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth if (ShowColors) 7626ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth OS.resetColor(); 7636ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth OS << '\n'; 7646ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth} 7656ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 7666ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/// \brief Print out the file/line/column information and include trace. 7676ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/// 7686ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/// This method handlen the emission of the diagnostic location information. 7696ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/// This includes extracting as much location information as is present for 7706ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/// the diagnostic and printing it, as well as any include stack or source 7716ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth/// ranges necessary. 7727531f571808201d44002fa38b67ee0a81e5ae936Chandler Carruthvoid TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, 7736ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth DiagnosticsEngine::Level Level, 77416afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis ArrayRef<CharSourceRange> Ranges, 77516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager &SM) { 7766ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth if (PLoc.isInvalid()) { 7776ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth // At least print the file name if available: 7786ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth FileID FID = SM.getFileID(Loc); 7796ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth if (!FID.isInvalid()) { 7806ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth const FileEntry* FE = SM.getFileEntryForID(FID); 781651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (FE && FE->isValid()) { 7826ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth OS << FE->getName(); 7830fda0f75f053ad9afdb2bb8d4ea72c5e6a49d657Rafael Espindola if (FE->isInPCH()) 7846ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth OS << " (in PCH)"; 7856ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth OS << ": "; 7866ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth } 7876ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth } 7886ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth return; 7896ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth } 7906ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth unsigned LineNo = PLoc.getLine(); 7916ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 79202c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (!DiagOpts->ShowLocation) 7936ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth return; 7946ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 79502c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (DiagOpts->ShowColors) 7966ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth OS.changeColor(savedColor, true); 7976ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 7986ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth OS << PLoc.getFilename(); 799dc7b641574a733624489bd87fc7061771edf2113Douglas Gregor switch (DiagOpts->getFormat()) { 8006ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth case DiagnosticOptions::Clang: OS << ':' << LineNo; break; 8016ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth case DiagnosticOptions::Msvc: OS << '(' << LineNo; break; 8026ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth case DiagnosticOptions::Vi: OS << " +" << LineNo; break; 8036ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth } 8046ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 80502c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (DiagOpts->ShowColumn) 8066ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth // Compute the column number. 8076ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth if (unsigned ColNo = PLoc.getColumn()) { 808dc7b641574a733624489bd87fc7061771edf2113Douglas Gregor if (DiagOpts->getFormat() == DiagnosticOptions::Msvc) { 8096ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth OS << ','; 810651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Visual Studio 2010 or earlier expects column number to be off by one 811ef8225444452a1486bd721f3285301fe84643b00Stephen Hines if (LangOpts.MSCVersion && LangOpts.MSCVersion < 170000000) 812651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ColNo--; 8136ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth } else 8146ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth OS << ':'; 8156ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth OS << ColNo; 8166ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth } 817dc7b641574a733624489bd87fc7061771edf2113Douglas Gregor switch (DiagOpts->getFormat()) { 8186ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth case DiagnosticOptions::Clang: 8196ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth case DiagnosticOptions::Vi: OS << ':'; break; 8206ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth case DiagnosticOptions::Msvc: OS << ") : "; break; 8216ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth } 8226ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 82302c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (DiagOpts->ShowSourceRanges && !Ranges.empty()) { 8246ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth FileID CaretFileID = 8256ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth SM.getFileID(SM.getExpansionLoc(Loc)); 8266ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth bool PrintedRange = false; 8276ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 8286ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth for (ArrayRef<CharSourceRange>::const_iterator RI = Ranges.begin(), 8296ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth RE = Ranges.end(); 8306ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth RI != RE; ++RI) { 8316ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth // Ignore invalid ranges. 8326ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth if (!RI->isValid()) continue; 8336ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 8346ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth SourceLocation B = SM.getExpansionLoc(RI->getBegin()); 8356ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth SourceLocation E = SM.getExpansionLoc(RI->getEnd()); 8366ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 8376ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth // If the End location and the start location are the same and are a 8386ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth // macro location, then the range was something that came from a 8396ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth // macro expansion or _Pragma. If this is an object-like macro, the 8406ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth // best we can do is to highlight the range. If this is a 8416ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth // function-like macro, we'd also like to highlight the arguments. 8426ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth if (B == E && RI->getEnd().isMacroID()) 8436ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth E = SM.getExpansionRange(RI->getEnd()).second; 8446ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 8456ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B); 8466ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E); 8476ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 8486ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth // If the start or end of the range is in another file, just discard 8496ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth // it. 8506ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth if (BInfo.first != CaretFileID || EInfo.first != CaretFileID) 8516ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth continue; 8526ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 8536ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth // Add in the length of the token, so that we cover multi-char 8546ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth // tokens. 8556ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth unsigned TokSize = 0; 8566ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth if (RI->isTokenRange()) 8576ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth TokSize = Lexer::MeasureTokenLength(E, SM, LangOpts); 8586ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 8596ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':' 8606ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth << SM.getColumnNumber(BInfo.first, BInfo.second) << '-' 8616ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth << SM.getLineNumber(EInfo.first, EInfo.second) << ':' 8626ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth << (SM.getColumnNumber(EInfo.first, EInfo.second)+TokSize) 8636ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth << '}'; 8646ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth PrintedRange = true; 8656ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth } 8666ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 8676ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth if (PrintedRange) 8686ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth OS << ':'; 8696ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth } 8706ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth OS << ' '; 8716ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth} 8726ddd8871c07ab161742e8ed37d3ef121ac79fa59Chandler Carruth 8732898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenekvoid TextDiagnostic::emitIncludeLocation(SourceLocation Loc, 87416afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis PresumedLoc PLoc, 87516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager &SM) { 87602c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (DiagOpts->ShowLocation) 8772898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek OS << "In file included from " << PLoc.getFilename() << ':' 8782898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek << PLoc.getLine() << ":\n"; 8792898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek else 8802898d4f7648e6ed5e9047068f1e8ee2f3c2bcd75Ted Kremenek OS << "In included file:\n"; 881db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth} 882db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 8836c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregorvoid TextDiagnostic::emitImportLocation(SourceLocation Loc, PresumedLoc PLoc, 8846c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor StringRef ModuleName, 8856c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor const SourceManager &SM) { 8866c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor if (DiagOpts->ShowLocation) 8876c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor OS << "In module '" << ModuleName << "' imported from " 8886c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor << PLoc.getFilename() << ':' << PLoc.getLine() << ":\n"; 8896c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor else 8906c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor OS << "In module " << ModuleName << "':\n"; 8916c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor} 8926c3254316de2d0d554b19702f4b10117ae46b77bDouglas Gregor 893830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregorvoid TextDiagnostic::emitBuildingModuleLocation(SourceLocation Loc, 894830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor PresumedLoc PLoc, 895830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor StringRef ModuleName, 896830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor const SourceManager &SM) { 897813bc7faa74bda8162db3dede57e07bfe764e86eDouglas Gregor if (DiagOpts->ShowLocation && PLoc.getFilename()) 898830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor OS << "While building module '" << ModuleName << "' imported from " 899830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor << PLoc.getFilename() << ':' << PLoc.getLine() << ":\n"; 900830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor else 901830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor OS << "While building module '" << ModuleName << "':\n"; 902830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor} 903830ea5b7c75413526c19531f0180fa6e45b98919Douglas Gregor 904c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer/// \brief Highlight a SourceRange (with ~'s) for any characters on LineNo. 905c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramerstatic void highlightRange(const CharSourceRange &R, 906c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer unsigned LineNo, FileID FID, 907c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer const SourceColumnMap &map, 908c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer std::string &CaretLine, 909c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer const SourceManager &SM, 910c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer const LangOptions &LangOpts) { 911c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer if (!R.isValid()) return; 912c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 913c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer SourceLocation Begin = R.getBegin(); 914c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer SourceLocation End = R.getEnd(); 915c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 916c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer unsigned StartLineNo = SM.getExpansionLineNumber(Begin); 917c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer if (StartLineNo > LineNo || SM.getFileID(Begin) != FID) 918c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer return; // No intersection. 919c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 920c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer unsigned EndLineNo = SM.getExpansionLineNumber(End); 921c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer if (EndLineNo < LineNo || SM.getFileID(End) != FID) 922c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer return; // No intersection. 923c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 924c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // Compute the column number of the start. 925c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer unsigned StartColNo = 0; 926c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer if (StartLineNo == LineNo) { 927c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer StartColNo = SM.getExpansionColumnNumber(Begin); 928c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer if (StartColNo) --StartColNo; // Zero base the col #. 929c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer } 930c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 931c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // Compute the column number of the end. 932c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer unsigned EndColNo = map.getSourceLine().size(); 933c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer if (EndLineNo == LineNo) { 934c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer EndColNo = SM.getExpansionColumnNumber(End); 935c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer if (EndColNo) { 936c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer --EndColNo; // Zero base the col #. 937c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 938c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // Add in the length of the token, so that we cover multi-char tokens if 939c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // this is a token range. 940c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer if (R.isTokenRange()) 941c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer EndColNo += Lexer::MeasureTokenLength(End, SM, LangOpts); 942c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer } else { 943c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer EndColNo = CaretLine.size(); 944c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer } 945c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer } 946c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 947c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer assert(StartColNo <= EndColNo && "Invalid range!"); 948c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 949c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // Check that a token range does not highlight only whitespace. 950c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer if (R.isTokenRange()) { 951c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // Pick the first non-whitespace column. 952c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer while (StartColNo < map.getSourceLine().size() && 953c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer (map.getSourceLine()[StartColNo] == ' ' || 954c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer map.getSourceLine()[StartColNo] == '\t')) 955c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer StartColNo = map.startOfNextColumn(StartColNo); 956c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 957c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // Pick the last non-whitespace column. 958c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer if (EndColNo > map.getSourceLine().size()) 959c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer EndColNo = map.getSourceLine().size(); 960316dd5467bed9242088149fe92f3316ef4f235e9Ted Kremenek while (EndColNo && 961c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer (map.getSourceLine()[EndColNo-1] == ' ' || 962c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer map.getSourceLine()[EndColNo-1] == '\t')) 963c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer EndColNo = map.startOfPreviousColumn(EndColNo); 964c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 965c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // If the start/end passed each other, then we are trying to highlight a 966c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // range that just exists in whitespace, which must be some sort of other 967c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // bug. 968c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer assert(StartColNo <= EndColNo && "Trying to highlight whitespace??"); 969c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer } 970c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 971c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer assert(StartColNo <= map.getSourceLine().size() && "Invalid range!"); 972c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer assert(EndColNo <= map.getSourceLine().size() && "Invalid range!"); 973c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 974c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // Fill the range with ~'s. 975c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer StartColNo = map.byteToContainingColumn(StartColNo); 976c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer EndColNo = map.byteToContainingColumn(EndColNo); 977c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 978c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer assert(StartColNo <= EndColNo && "Invalid range!"); 979c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer if (CaretLine.size() < EndColNo) 980c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer CaretLine.resize(EndColNo,' '); 981c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer std::fill(CaretLine.begin()+StartColNo,CaretLine.begin()+EndColNo,'~'); 982c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer} 983c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 984c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramerstatic std::string buildFixItInsertionLine(unsigned LineNo, 985c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer const SourceColumnMap &map, 986c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer ArrayRef<FixItHint> Hints, 987c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer const SourceManager &SM, 988c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer const DiagnosticOptions *DiagOpts) { 989c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer std::string FixItInsertionLine; 990c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer if (Hints.empty() || !DiagOpts->ShowFixits) 991c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer return FixItInsertionLine; 992c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer unsigned PrevHintEndCol = 0; 993c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 994c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end(); 995c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer I != E; ++I) { 996c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer if (!I->CodeToInsert.empty()) { 997c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // We have an insertion hint. Determine whether the inserted 998c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // code contains no newlines and is on the same line as the caret. 999c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer std::pair<FileID, unsigned> HintLocInfo 1000c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer = SM.getDecomposedExpansionLoc(I->RemoveRange.getBegin()); 1001c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer if (LineNo == SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) && 1002c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer StringRef(I->CodeToInsert).find_first_of("\n\r") == StringRef::npos) { 1003c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // Insert the new code into the line just below the code 1004c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // that the user wrote. 1005c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // Note: When modifying this function, be very careful about what is a 1006c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // "column" (printed width, platform-dependent) and what is a 1007c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // "byte offset" (SourceManager "column"). 1008c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer unsigned HintByteOffset 1009c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer = SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second) - 1; 1010c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 1011c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // The hint must start inside the source or right at the end 1012c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer assert(HintByteOffset < static_cast<unsigned>(map.bytes())+1); 1013c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer unsigned HintCol = map.byteToContainingColumn(HintByteOffset); 1014c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 1015c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // If we inserted a long previous hint, push this one forwards, and add 1016c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // an extra space to show that this is not part of the previous 1017c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // completion. This is sort of the best we can do when two hints appear 1018c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // to overlap. 1019c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // 1020c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // Note that if this hint is located immediately after the previous 1021c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // hint, no space will be added, since the location is more important. 1022c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer if (HintCol < PrevHintEndCol) 1023c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer HintCol = PrevHintEndCol + 1; 1024c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 1025c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // This should NOT use HintByteOffset, because the source might have 1026c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer // Unicode characters in earlier columns. 10271f13fbd0c5bac045aa7d6ae3e998758e9dfa3ce4Jordan Rose unsigned NewFixItLineSize = FixItInsertionLine.size() + 10281f13fbd0c5bac045aa7d6ae3e998758e9dfa3ce4Jordan Rose (HintCol - PrevHintEndCol) + I->CodeToInsert.size(); 10291f13fbd0c5bac045aa7d6ae3e998758e9dfa3ce4Jordan Rose if (NewFixItLineSize > FixItInsertionLine.size()) 10301f13fbd0c5bac045aa7d6ae3e998758e9dfa3ce4Jordan Rose FixItInsertionLine.resize(NewFixItLineSize, ' '); 1031c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 1032c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer std::copy(I->CodeToInsert.begin(), I->CodeToInsert.end(), 10331f13fbd0c5bac045aa7d6ae3e998758e9dfa3ce4Jordan Rose FixItInsertionLine.end() - I->CodeToInsert.size()); 1034c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 10351f13fbd0c5bac045aa7d6ae3e998758e9dfa3ce4Jordan Rose PrevHintEndCol = 10361f13fbd0c5bac045aa7d6ae3e998758e9dfa3ce4Jordan Rose HintCol + llvm::sys::locale::columnWidth(I->CodeToInsert); 1037c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer } else { 1038c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer FixItInsertionLine.clear(); 1039c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer break; 1040c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer } 1041c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer } 1042c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer } 1043c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 1044c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer expandTabs(FixItInsertionLine, DiagOpts->TabStop); 1045c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 1046c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer return FixItInsertionLine; 1047c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer} 1048c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer 1049db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \brief Emit a code snippet and caret line. 1050db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// 1051db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// This routine emits a single line's code snippet and caret line.. 1052db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// 1053db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Loc The location for the caret. 1054db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Ranges The underlined ranges for this code snippet. 1055db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth/// \param Hints The FixIt hints active for this diagnostic. 10567531f571808201d44002fa38b67ee0a81e5ae936Chandler Carruthvoid TextDiagnostic::emitSnippetAndCaret( 10574ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth SourceLocation Loc, DiagnosticsEngine::Level Level, 1058db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth SmallVectorImpl<CharSourceRange>& Ranges, 105916afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis ArrayRef<FixItHint> Hints, 106016afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager &SM) { 1061db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth assert(!Loc.isInvalid() && "must have a valid source location here"); 1062db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth assert(Loc.isFileID() && "must have a file location here"); 1063db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 10644ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth // If caret diagnostics are enabled and we have location, we want to 10654ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth // emit the caret. However, we only do this if the location moved 10664ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth // from the last diagnostic, if the last diagnostic was a note that 10674ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth // was part of a different warning or error diagnostic, or if the 10684ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth // diagnostic has ranges. We don't want to emit the same caret 10694ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth // multiple times if one loc has multiple diagnostics. 107002c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (!DiagOpts->ShowCarets) 10714ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth return; 10724ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth if (Loc == LastLoc && Ranges.empty() && Hints.empty() && 10734ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth (LastLevel != DiagnosticsEngine::Note || Level == LastLevel)) 10744ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth return; 10754ba55659982bf45eedc9d32851815e5c4b6d8460Chandler Carruth 1076db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Decompose the location into a FID/Offset pair. 1077db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); 1078db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth FileID FID = LocInfo.first; 1079db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth unsigned FileOffset = LocInfo.second; 1080db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1081db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Get information about the buffer it points into. 1082db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth bool Invalid = false; 108340d8e971a32a23856ce1ab0106ae75cf4b92ca9dNico Weber const char *BufStart = SM.getBufferData(FID, &Invalid).data(); 1084db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth if (Invalid) 1085db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth return; 1086db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1087db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth unsigned LineNo = SM.getLineNumber(FID, FileOffset); 1088db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth unsigned ColNo = SM.getColumnNumber(FID, FileOffset); 1089f6e74a35e0c0e53b2e65fc9fe86f8e4cadcca473Jordan Rose 1090f6e74a35e0c0e53b2e65fc9fe86f8e4cadcca473Jordan Rose // Arbitrarily stop showing snippets when the line is too long. 1091dd3e2d90418de46b77a9dde3bb992390610e343aBenjamin Kramer static const size_t MaxLineLengthToPrint = 4096; 109291165e74c8b480c1da3a719d764f4fa0e7b1b921Jordan Rose if (ColNo > MaxLineLengthToPrint) 1093f6e74a35e0c0e53b2e65fc9fe86f8e4cadcca473Jordan Rose return; 1094db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1095db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Rewind from the current position to the start of the line. 1096db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth const char *TokPtr = BufStart+FileOffset; 1097db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based. 1098db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1099db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Compute the line end. Scan forward from the error position to the end of 1100db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // the line. 1101db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth const char *LineEnd = TokPtr; 110240d8e971a32a23856ce1ab0106ae75cf4b92ca9dNico Weber while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0') 1103db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth ++LineEnd; 1104db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1105f6e74a35e0c0e53b2e65fc9fe86f8e4cadcca473Jordan Rose // Arbitrarily stop showing snippets when the line is too long. 1106dd3e2d90418de46b77a9dde3bb992390610e343aBenjamin Kramer if (size_t(LineEnd - LineStart) > MaxLineLengthToPrint) 1107f6e74a35e0c0e53b2e65fc9fe86f8e4cadcca473Jordan Rose return; 1108f6e74a35e0c0e53b2e65fc9fe86f8e4cadcca473Jordan Rose 1109db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Copy the line of code into an std::string for ease of manipulation. 1110db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth std::string SourceLine(LineStart, LineEnd); 1111db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1112db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Create a line for the caret that is filled with spaces that is the same 1113db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // length as the line of source code. 1114db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth std::string CaretLine(LineEnd-LineStart, ' '); 1115db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 111602c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor const SourceColumnMap sourceColMap(SourceLine, DiagOpts->TabStop); 11176749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 1118db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Highlight all of the characters covered by Ranges with ~ characters. 1119db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(), 1120db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth E = Ranges.end(); 1121db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth I != E; ++I) 1122c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM, LangOpts); 1123db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1124db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Next, insert the caret itself. 1125c7bb384d608aeae23a6c95114569da0c3eae10feRichard Smith ColNo = sourceColMap.byteToContainingColumn(ColNo-1); 11266749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (CaretLine.size()<ColNo+1) 11276749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell CaretLine.resize(ColNo+1, ' '); 11286749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell CaretLine[ColNo] = '^'; 1129e9a3b76ba589a8a884e978273beaed0d97cf9861Seth Cantrell 11306749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell std::string FixItInsertionLine = buildFixItInsertionLine(LineNo, 11316749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell sourceColMap, 1132c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer Hints, SM, 1133ef8225444452a1486bd721f3285301fe84643b00Stephen Hines DiagOpts.get()); 11346749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 11356749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell // If the source line is too long for our terminal, select only the 11366749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell // "interesting" source region within that line. 113702c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor unsigned Columns = DiagOpts->MessageLength; 11386749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (Columns) 11396749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine, 11406749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell Columns, sourceColMap); 1141db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1142db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // If we are in -fdiagnostics-print-source-range-info mode, we are trying 1143db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // to produce easily machine parsable output. Add a space before the 1144db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // source line and the caret to make it trivial to tell the main diagnostic 1145db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // line from what the user is intended to see. 114602c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (DiagOpts->ShowSourceRanges) { 1147db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth SourceLine = ' ' + SourceLine; 1148db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth CaretLine = ' ' + CaretLine; 1149db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth } 1150db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1151db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Finally, remove any blank spaces from the end of CaretLine. 1152db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth while (CaretLine[CaretLine.size()-1] == ' ') 1153db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth CaretLine.erase(CaretLine.end()-1); 1154db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1155db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Emit what we have computed. 11566749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell emitSnippet(SourceLine); 1157db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 115802c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (DiagOpts->ShowColors) 1159db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth OS.changeColor(caretColor, true); 1160db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth OS << CaretLine << '\n'; 116102c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (DiagOpts->ShowColors) 1162db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth OS.resetColor(); 1163db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1164db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth if (!FixItInsertionLine.empty()) { 116502c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (DiagOpts->ShowColors) 1166db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Print fixit line in color 1167db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth OS.changeColor(fixitColor, false); 116802c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (DiagOpts->ShowSourceRanges) 1169db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth OS << ' '; 1170db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth OS << FixItInsertionLine << '\n'; 117102c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (DiagOpts->ShowColors) 1172db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth OS.resetColor(); 1173db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth } 1174db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1175db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Print out any parseable fixit information requested by the options. 117616afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis emitParseableFixits(Hints, SM); 1177db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth} 1178db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1179d1fda0393b50c9c1ea25925725916da3ce13c1e2Benjamin Kramervoid TextDiagnostic::emitSnippet(StringRef line) { 11806749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (line.empty()) 11816749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell return; 11826749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 11836749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell size_t i = 0; 11846749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 11856749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell std::string to_print; 11866749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell bool print_reversed = false; 11876749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 11886749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell while (i<line.size()) { 11896749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell std::pair<SmallString<16>,bool> res 119002c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor = printableTextForNextCharacter(line, &i, DiagOpts->TabStop); 11916749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell bool was_printable = res.second; 11926749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 119302c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (DiagOpts->ShowColors && was_printable == print_reversed) { 11946749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell if (print_reversed) 11956749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell OS.reverseColor(); 11966749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell OS << to_print; 11976749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell to_print.clear(); 119802c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (DiagOpts->ShowColors) 11996749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell OS.resetColor(); 12006749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell } 12016749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 12026749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell print_reversed = !was_printable; 12036749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell to_print += res.first.str(); 12046749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell } 12056749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 120602c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (print_reversed && DiagOpts->ShowColors) 12076749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell OS.reverseColor(); 12086749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell OS << to_print; 120902c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (print_reversed && DiagOpts->ShowColors) 12106749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell OS.resetColor(); 12116749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 12126749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell OS << '\n'; 12136749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell} 12146749dd50869281f9b49ad5960e25288c15a71cacSeth Cantrell 121516afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidisvoid TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints, 121616afdf76b6f12e41ff6f6e6828bfb1d4732523baArgyrios Kyrtzidis const SourceManager &SM) { 121702c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (!DiagOpts->ShowParseableFixits) 1218db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth return; 1219db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1220db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // We follow FixItRewriter's example in not (yet) handling 1221db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // fix-its in macros. 1222db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end(); 1223db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth I != E; ++I) { 1224db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth if (I->RemoveRange.isInvalid() || 1225db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth I->RemoveRange.getBegin().isMacroID() || 1226db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth I->RemoveRange.getEnd().isMacroID()) 1227db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth return; 1228db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth } 1229db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1230db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end(); 1231db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth I != E; ++I) { 1232db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth SourceLocation BLoc = I->RemoveRange.getBegin(); 1233db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth SourceLocation ELoc = I->RemoveRange.getEnd(); 1234db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1235db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc); 1236db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc); 1237db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1238db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // Adjust for token ranges. 1239db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth if (I->RemoveRange.isTokenRange()) 1240db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, LangOpts); 1241db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1242db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // We specifically do not do word-wrapping or tab-expansion here, 1243db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth // because this is supposed to be easy to parse. 1244db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth PresumedLoc PLoc = SM.getPresumedLoc(BLoc); 1245db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth if (PLoc.isInvalid()) 1246db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth break; 1247db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth 1248db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth OS << "fix-it:\""; 1249db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth OS.write_escaped(PLoc.getFilename()); 1250db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth OS << "\":{" << SM.getLineNumber(BInfo.first, BInfo.second) 1251db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth << ':' << SM.getColumnNumber(BInfo.first, BInfo.second) 1252db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth << '-' << SM.getLineNumber(EInfo.first, EInfo.second) 1253db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth << ':' << SM.getColumnNumber(EInfo.first, EInfo.second) 1254db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth << "}:\""; 1255db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth OS.write_escaped(I->CodeToInsert); 1256db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth OS << "\"\n"; 1257db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth } 1258db463bb2e4a9751f4cbe53996db751e1985ee966Chandler Carruth} 1259