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