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