TextDiagnosticPrinter.cpp revision 45b19dea3633737cabdd9a86477f7f2e07024595
1//===--- TextDiagnosticPrinter.cpp - Diagnostic Printer -------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This diagnostic client prints out their diagnostic messages. 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/Frontend/TextDiagnosticPrinter.h" 15#include "clang/Basic/FileManager.h" 16#include "clang/Basic/SourceManager.h" 17#include "clang/Frontend/DiagnosticOptions.h" 18#include "clang/Lex/Lexer.h" 19#include "llvm/Support/MemoryBuffer.h" 20#include "llvm/Support/raw_ostream.h" 21#include "llvm/Support/ErrorHandling.h" 22#include "llvm/ADT/SmallString.h" 23#include "llvm/ADT/StringExtras.h" 24#include <algorithm> 25using namespace clang; 26 27static const enum raw_ostream::Colors noteColor = 28 raw_ostream::BLACK; 29static const enum raw_ostream::Colors fixitColor = 30 raw_ostream::GREEN; 31static const enum raw_ostream::Colors caretColor = 32 raw_ostream::GREEN; 33static const enum raw_ostream::Colors warningColor = 34 raw_ostream::MAGENTA; 35static const enum raw_ostream::Colors errorColor = raw_ostream::RED; 36static const enum raw_ostream::Colors fatalColor = raw_ostream::RED; 37// Used for changing only the bold attribute. 38static const enum raw_ostream::Colors savedColor = 39 raw_ostream::SAVEDCOLOR; 40 41/// \brief Number of spaces to indent when word-wrapping. 42const unsigned WordWrapIndentation = 6; 43 44TextDiagnosticPrinter::TextDiagnosticPrinter(raw_ostream &os, 45 const DiagnosticOptions &diags, 46 bool _OwnsOutputStream) 47 : OS(os), LangOpts(0), DiagOpts(&diags), 48 LastCaretDiagnosticWasNote(0), 49 OwnsOutputStream(_OwnsOutputStream) { 50} 51 52TextDiagnosticPrinter::~TextDiagnosticPrinter() { 53 if (OwnsOutputStream) 54 delete &OS; 55} 56 57/// \brief Helper to recursivly walk up the include stack and print each layer 58/// on the way back down. 59static void PrintIncludeStackRecursively(raw_ostream &OS, 60 const SourceManager &SM, 61 SourceLocation Loc, 62 bool ShowLocation) { 63 if (Loc.isInvalid()) 64 return; 65 66 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 67 if (PLoc.isInvalid()) 68 return; 69 70 // Print out the other include frames first. 71 PrintIncludeStackRecursively(OS, SM, PLoc.getIncludeLoc(), ShowLocation); 72 73 if (ShowLocation) 74 OS << "In file included from " << PLoc.getFilename() 75 << ':' << PLoc.getLine() << ":\n"; 76 else 77 OS << "In included file:\n"; 78} 79 80/// \brief Prints an include stack when appropriate for a particular diagnostic 81/// level and location. 82/// 83/// This routine handles all the logic of suppressing particular include stacks 84/// (such as those for notes) and duplicate include stacks when repeated 85/// warnings occur within the same file. It also handles the logic of 86/// customizing the formatting and display of the include stack. 87/// 88/// \param Level The diagnostic level of the message this stack pertains to. 89/// \param Loc The include location of the current file (not the diagnostic 90/// location). 91void TextDiagnosticPrinter::PrintIncludeStack(DiagnosticsEngine::Level Level, 92 SourceLocation Loc, 93 const SourceManager &SM) { 94 // Skip redundant include stacks altogether. 95 if (LastWarningLoc == Loc) 96 return; 97 LastWarningLoc = Loc; 98 99 if (!DiagOpts->ShowNoteIncludeStack && Level == DiagnosticsEngine::Note) 100 return; 101 102 PrintIncludeStackRecursively(OS, SM, Loc, DiagOpts->ShowLocation); 103} 104 105/// \brief When the source code line we want to print is too long for 106/// the terminal, select the "interesting" region. 107static void SelectInterestingSourceRegion(std::string &SourceLine, 108 std::string &CaretLine, 109 std::string &FixItInsertionLine, 110 unsigned EndOfCaretToken, 111 unsigned Columns) { 112 unsigned MaxSize = std::max(SourceLine.size(), 113 std::max(CaretLine.size(), 114 FixItInsertionLine.size())); 115 if (MaxSize > SourceLine.size()) 116 SourceLine.resize(MaxSize, ' '); 117 if (MaxSize > CaretLine.size()) 118 CaretLine.resize(MaxSize, ' '); 119 if (!FixItInsertionLine.empty() && MaxSize > FixItInsertionLine.size()) 120 FixItInsertionLine.resize(MaxSize, ' '); 121 122 // Find the slice that we need to display the full caret line 123 // correctly. 124 unsigned CaretStart = 0, CaretEnd = CaretLine.size(); 125 for (; CaretStart != CaretEnd; ++CaretStart) 126 if (!isspace(CaretLine[CaretStart])) 127 break; 128 129 for (; CaretEnd != CaretStart; --CaretEnd) 130 if (!isspace(CaretLine[CaretEnd - 1])) 131 break; 132 133 // Make sure we don't chop the string shorter than the caret token 134 // itself. 135 if (CaretEnd < EndOfCaretToken) 136 CaretEnd = EndOfCaretToken; 137 138 // If we have a fix-it line, make sure the slice includes all of the 139 // fix-it information. 140 if (!FixItInsertionLine.empty()) { 141 unsigned FixItStart = 0, FixItEnd = FixItInsertionLine.size(); 142 for (; FixItStart != FixItEnd; ++FixItStart) 143 if (!isspace(FixItInsertionLine[FixItStart])) 144 break; 145 146 for (; FixItEnd != FixItStart; --FixItEnd) 147 if (!isspace(FixItInsertionLine[FixItEnd - 1])) 148 break; 149 150 if (FixItStart < CaretStart) 151 CaretStart = FixItStart; 152 if (FixItEnd > CaretEnd) 153 CaretEnd = FixItEnd; 154 } 155 156 // CaretLine[CaretStart, CaretEnd) contains all of the interesting 157 // parts of the caret line. While this slice is smaller than the 158 // number of columns we have, try to grow the slice to encompass 159 // more context. 160 161 // If the end of the interesting region comes before we run out of 162 // space in the terminal, start at the beginning of the line. 163 if (Columns > 3 && CaretEnd < Columns - 3) 164 CaretStart = 0; 165 166 unsigned TargetColumns = Columns; 167 if (TargetColumns > 8) 168 TargetColumns -= 8; // Give us extra room for the ellipses. 169 unsigned SourceLength = SourceLine.size(); 170 while ((CaretEnd - CaretStart) < TargetColumns) { 171 bool ExpandedRegion = false; 172 // Move the start of the interesting region left until we've 173 // pulled in something else interesting. 174 if (CaretStart == 1) 175 CaretStart = 0; 176 else if (CaretStart > 1) { 177 unsigned NewStart = CaretStart - 1; 178 179 // Skip over any whitespace we see here; we're looking for 180 // another bit of interesting text. 181 while (NewStart && isspace(SourceLine[NewStart])) 182 --NewStart; 183 184 // Skip over this bit of "interesting" text. 185 while (NewStart && !isspace(SourceLine[NewStart])) 186 --NewStart; 187 188 // Move up to the non-whitespace character we just saw. 189 if (NewStart) 190 ++NewStart; 191 192 // If we're still within our limit, update the starting 193 // position within the source/caret line. 194 if (CaretEnd - NewStart <= TargetColumns) { 195 CaretStart = NewStart; 196 ExpandedRegion = true; 197 } 198 } 199 200 // Move the end of the interesting region right until we've 201 // pulled in something else interesting. 202 if (CaretEnd != SourceLength) { 203 assert(CaretEnd < SourceLength && "Unexpected caret position!"); 204 unsigned NewEnd = CaretEnd; 205 206 // Skip over any whitespace we see here; we're looking for 207 // another bit of interesting text. 208 while (NewEnd != SourceLength && isspace(SourceLine[NewEnd - 1])) 209 ++NewEnd; 210 211 // Skip over this bit of "interesting" text. 212 while (NewEnd != SourceLength && !isspace(SourceLine[NewEnd - 1])) 213 ++NewEnd; 214 215 if (NewEnd - CaretStart <= TargetColumns) { 216 CaretEnd = NewEnd; 217 ExpandedRegion = true; 218 } 219 } 220 221 if (!ExpandedRegion) 222 break; 223 } 224 225 // [CaretStart, CaretEnd) is the slice we want. Update the various 226 // output lines to show only this slice, with two-space padding 227 // before the lines so that it looks nicer. 228 if (CaretEnd < SourceLine.size()) 229 SourceLine.replace(CaretEnd, std::string::npos, "..."); 230 if (CaretEnd < CaretLine.size()) 231 CaretLine.erase(CaretEnd, std::string::npos); 232 if (FixItInsertionLine.size() > CaretEnd) 233 FixItInsertionLine.erase(CaretEnd, std::string::npos); 234 235 if (CaretStart > 2) { 236 SourceLine.replace(0, CaretStart, " ..."); 237 CaretLine.replace(0, CaretStart, " "); 238 if (FixItInsertionLine.size() >= CaretStart) 239 FixItInsertionLine.replace(0, CaretStart, " "); 240 } 241} 242 243/// Look through spelling locations for a macro argument expansion, and 244/// if found skip to it so that we can trace the argument rather than the macros 245/// in which that argument is used. If no macro argument expansion is found, 246/// don't skip anything and return the starting location. 247static SourceLocation skipToMacroArgExpansion(const SourceManager &SM, 248 SourceLocation StartLoc) { 249 for (SourceLocation L = StartLoc; L.isMacroID(); 250 L = SM.getImmediateSpellingLoc(L)) { 251 if (SM.isMacroArgExpansion(L)) 252 return L; 253 } 254 255 // Otherwise just return initial location, there's nothing to skip. 256 return StartLoc; 257} 258 259/// Gets the location of the immediate macro caller, one level up the stack 260/// toward the initial macro typed into the source. 261static SourceLocation getImmediateMacroCallerLoc(const SourceManager &SM, 262 SourceLocation Loc) { 263 if (!Loc.isMacroID()) return Loc; 264 265 // When we have the location of (part of) an expanded parameter, its spelling 266 // location points to the argument as typed into the macro call, and 267 // therefore is used to locate the macro caller. 268 if (SM.isMacroArgExpansion(Loc)) 269 return SM.getImmediateSpellingLoc(Loc); 270 271 // Otherwise, the caller of the macro is located where this macro is 272 // expanded (while the spelling is part of the macro definition). 273 return SM.getImmediateExpansionRange(Loc).first; 274} 275 276/// Gets the location of the immediate macro callee, one level down the stack 277/// toward the leaf macro. 278static SourceLocation getImmediateMacroCalleeLoc(const SourceManager &SM, 279 SourceLocation Loc) { 280 if (!Loc.isMacroID()) return Loc; 281 282 // When we have the location of (part of) an expanded parameter, its 283 // expansion location points to the unexpanded paramater reference within 284 // the macro definition (or callee). 285 if (SM.isMacroArgExpansion(Loc)) 286 return SM.getImmediateExpansionRange(Loc).first; 287 288 // Otherwise, the callee of the macro is located where this location was 289 // spelled inside the macro definition. 290 return SM.getImmediateSpellingLoc(Loc); 291} 292 293namespace { 294 295/// \brief Class to encapsulate the logic for formatting and printing a textual 296/// diagnostic message. 297/// 298/// This class provides an interface for building and emitting a textual 299/// diagnostic, including all of the macro backtraces, caret diagnostics, FixIt 300/// Hints, and code snippets. In the presence of macros this involves 301/// a recursive process, synthesizing notes for each macro expansion. 302/// 303/// The purpose of this class is to isolate the implementation of printing 304/// beautiful text diagnostics from any particular interfaces. The Clang 305/// DiagnosticClient is implemented through this class as is diagnostic 306/// printing coming out of libclang. 307/// 308/// A brief worklist: 309/// FIXME: Sink the printing of the diagnostic message itself into this class. 310/// FIXME: Sink the printing of the include stack into this class. 311/// FIXME: Remove the TextDiagnosticPrinter as an input. 312/// FIXME: Sink the recursive printing of template instantiations into this 313/// class. 314class TextDiagnostic { 315 TextDiagnosticPrinter &Printer; 316 raw_ostream &OS; 317 const SourceManager &SM; 318 const LangOptions &LangOpts; 319 const DiagnosticOptions &DiagOpts; 320 321public: 322 TextDiagnostic(TextDiagnosticPrinter &Printer, 323 raw_ostream &OS, 324 const SourceManager &SM, 325 const LangOptions &LangOpts, 326 const DiagnosticOptions &DiagOpts) 327 : Printer(Printer), OS(OS), SM(SM), LangOpts(LangOpts), DiagOpts(DiagOpts) { 328 } 329 330 /// \brief Emit the caret diagnostic text. 331 /// 332 /// Walks up the macro expansion stack printing the code snippet, caret, 333 /// underlines and FixItHint display as appropriate at each level. Walk is 334 /// accomplished by calling itself recursively. 335 /// 336 /// FIXME: Break up massive function into logical units. 337 /// 338 /// \param Loc The location for this caret. 339 /// \param Ranges The underlined ranges for this code snippet. 340 /// \param Hints The FixIt hints active for this diagnostic. 341 /// \param MacroSkipEnd The depth to stop skipping macro expansions. 342 /// \param OnMacroInst The current depth of the macro expansion stack. 343 void Emit(SourceLocation Loc, 344 SmallVectorImpl<CharSourceRange>& Ranges, 345 ArrayRef<FixItHint> Hints, 346 unsigned &MacroDepth, 347 unsigned OnMacroInst = 0) { 348 assert(!Loc.isInvalid() && "must have a valid source location here"); 349 350 // If this is a file source location, directly emit the source snippet and 351 // caret line. Also record the macro depth reached. 352 if (Loc.isFileID()) { 353 assert(MacroDepth == 0 && "We shouldn't hit a leaf node twice!"); 354 MacroDepth = OnMacroInst; 355 EmitSnippetAndCaret(Loc, Ranges, Hints); 356 return; 357 } 358 // Otherwise recurse through each macro expansion layer. 359 360 // When processing macros, skip over the expansions leading up to 361 // a macro argument, and trace the argument's expansion stack instead. 362 Loc = skipToMacroArgExpansion(SM, Loc); 363 364 SourceLocation OneLevelUp = getImmediateMacroCallerLoc(SM, Loc); 365 366 // FIXME: Map ranges? 367 Emit(OneLevelUp, Ranges, Hints, MacroDepth, OnMacroInst + 1); 368 369 // Map the location. 370 Loc = getImmediateMacroCalleeLoc(SM, Loc); 371 372 unsigned MacroSkipStart = 0, MacroSkipEnd = 0; 373 if (MacroDepth > DiagOpts.MacroBacktraceLimit) { 374 MacroSkipStart = DiagOpts.MacroBacktraceLimit / 2 + 375 DiagOpts.MacroBacktraceLimit % 2; 376 MacroSkipEnd = MacroDepth - DiagOpts.MacroBacktraceLimit / 2; 377 } 378 379 // Whether to suppress printing this macro expansion. 380 bool Suppressed = (OnMacroInst >= MacroSkipStart && 381 OnMacroInst < MacroSkipEnd); 382 383 // Map the ranges. 384 for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(), 385 E = Ranges.end(); 386 I != E; ++I) { 387 SourceLocation Start = I->getBegin(), End = I->getEnd(); 388 if (Start.isMacroID()) 389 I->setBegin(getImmediateMacroCalleeLoc(SM, Start)); 390 if (End.isMacroID()) 391 I->setEnd(getImmediateMacroCalleeLoc(SM, End)); 392 } 393 394 if (!Suppressed) { 395 // Don't print recursive expansion notes from an expansion note. 396 Loc = SM.getSpellingLoc(Loc); 397 398 // Get the pretty name, according to #line directives etc. 399 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 400 if (PLoc.isInvalid()) 401 return; 402 403 // If this diagnostic is not in the main file, print out the 404 // "included from" lines. 405 Printer.PrintIncludeStack(DiagnosticsEngine::Note, PLoc.getIncludeLoc(), 406 SM); 407 408 if (DiagOpts.ShowLocation) { 409 // Emit the file/line/column that this expansion came from. 410 OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':'; 411 if (DiagOpts.ShowColumn) 412 OS << PLoc.getColumn() << ':'; 413 OS << ' '; 414 } 415 OS << "note: expanded from:\n"; 416 417 EmitSnippetAndCaret(Loc, Ranges, ArrayRef<FixItHint>()); 418 return; 419 } 420 421 if (OnMacroInst == MacroSkipStart) { 422 // Tell the user that we've skipped contexts. 423 OS << "note: (skipping " << (MacroSkipEnd - MacroSkipStart) 424 << " expansions in backtrace; use -fmacro-backtrace-limit=0 to see " 425 "all)\n"; 426 } 427 } 428 429 /// \brief Emit a code snippet and caret line. 430 /// 431 /// This routine emits a single line's code snippet and caret line.. 432 /// 433 /// \param Loc The location for the caret. 434 /// \param Ranges The underlined ranges for this code snippet. 435 /// \param Hints The FixIt hints active for this diagnostic. 436 void EmitSnippetAndCaret(SourceLocation Loc, 437 SmallVectorImpl<CharSourceRange>& Ranges, 438 ArrayRef<FixItHint> Hints) { 439 assert(!Loc.isInvalid() && "must have a valid source location here"); 440 assert(Loc.isFileID() && "must have a file location here"); 441 442 // Decompose the location into a FID/Offset pair. 443 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); 444 FileID FID = LocInfo.first; 445 unsigned FileOffset = LocInfo.second; 446 447 // Get information about the buffer it points into. 448 bool Invalid = false; 449 const char *BufStart = SM.getBufferData(FID, &Invalid).data(); 450 if (Invalid) 451 return; 452 453 unsigned LineNo = SM.getLineNumber(FID, FileOffset); 454 unsigned ColNo = SM.getColumnNumber(FID, FileOffset); 455 unsigned CaretEndColNo 456 = ColNo + Lexer::MeasureTokenLength(Loc, SM, LangOpts); 457 458 // Rewind from the current position to the start of the line. 459 const char *TokPtr = BufStart+FileOffset; 460 const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based. 461 462 463 // Compute the line end. Scan forward from the error position to the end of 464 // the line. 465 const char *LineEnd = TokPtr; 466 while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0') 467 ++LineEnd; 468 469 // FIXME: This shouldn't be necessary, but the CaretEndColNo can extend past 470 // the source line length as currently being computed. See 471 // test/Misc/message-length.c. 472 CaretEndColNo = std::min(CaretEndColNo, unsigned(LineEnd - LineStart)); 473 474 // Copy the line of code into an std::string for ease of manipulation. 475 std::string SourceLine(LineStart, LineEnd); 476 477 // Create a line for the caret that is filled with spaces that is the same 478 // length as the line of source code. 479 std::string CaretLine(LineEnd-LineStart, ' '); 480 481 // Highlight all of the characters covered by Ranges with ~ characters. 482 for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(), 483 E = Ranges.end(); 484 I != E; ++I) 485 HighlightRange(*I, LineNo, FID, SourceLine, CaretLine); 486 487 // Next, insert the caret itself. 488 if (ColNo-1 < CaretLine.size()) 489 CaretLine[ColNo-1] = '^'; 490 else 491 CaretLine.push_back('^'); 492 493 ExpandTabs(SourceLine, CaretLine); 494 495 // If we are in -fdiagnostics-print-source-range-info mode, we are trying 496 // to produce easily machine parsable output. Add a space before the 497 // source line and the caret to make it trivial to tell the main diagnostic 498 // line from what the user is intended to see. 499 if (DiagOpts.ShowSourceRanges) { 500 SourceLine = ' ' + SourceLine; 501 CaretLine = ' ' + CaretLine; 502 } 503 504 std::string FixItInsertionLine = BuildFixItInsertionLine(LineNo, 505 LineStart, LineEnd, 506 Hints); 507 508 // If the source line is too long for our terminal, select only the 509 // "interesting" source region within that line. 510 unsigned Columns = DiagOpts.MessageLength; 511 if (Columns && SourceLine.size() > Columns) 512 SelectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine, 513 CaretEndColNo, Columns); 514 515 // Finally, remove any blank spaces from the end of CaretLine. 516 while (CaretLine[CaretLine.size()-1] == ' ') 517 CaretLine.erase(CaretLine.end()-1); 518 519 // Emit what we have computed. 520 OS << SourceLine << '\n'; 521 522 if (DiagOpts.ShowColors) 523 OS.changeColor(caretColor, true); 524 OS << CaretLine << '\n'; 525 if (DiagOpts.ShowColors) 526 OS.resetColor(); 527 528 if (!FixItInsertionLine.empty()) { 529 if (DiagOpts.ShowColors) 530 // Print fixit line in color 531 OS.changeColor(fixitColor, false); 532 if (DiagOpts.ShowSourceRanges) 533 OS << ' '; 534 OS << FixItInsertionLine << '\n'; 535 if (DiagOpts.ShowColors) 536 OS.resetColor(); 537 } 538 539 // Print out any parseable fixit information requested by the options. 540 EmitParseableFixits(Hints); 541 } 542 543private: 544 /// \brief Highlight a SourceRange (with ~'s) for any characters on LineNo. 545 void HighlightRange(const CharSourceRange &R, 546 unsigned LineNo, FileID FID, 547 const std::string &SourceLine, 548 std::string &CaretLine) { 549 assert(CaretLine.size() == SourceLine.size() && 550 "Expect a correspondence between source and caret line!"); 551 if (!R.isValid()) return; 552 553 SourceLocation Begin = SM.getExpansionLoc(R.getBegin()); 554 SourceLocation End = SM.getExpansionLoc(R.getEnd()); 555 556 // If the End location and the start location are the same and are a macro 557 // location, then the range was something that came from a macro expansion 558 // or _Pragma. If this is an object-like macro, the best we can do is to 559 // highlight the range. If this is a function-like macro, we'd also like to 560 // highlight the arguments. 561 if (Begin == End && R.getEnd().isMacroID()) 562 End = SM.getExpansionRange(R.getEnd()).second; 563 564 unsigned StartLineNo = SM.getExpansionLineNumber(Begin); 565 if (StartLineNo > LineNo || SM.getFileID(Begin) != FID) 566 return; // No intersection. 567 568 unsigned EndLineNo = SM.getExpansionLineNumber(End); 569 if (EndLineNo < LineNo || SM.getFileID(End) != FID) 570 return; // No intersection. 571 572 // Compute the column number of the start. 573 unsigned StartColNo = 0; 574 if (StartLineNo == LineNo) { 575 StartColNo = SM.getExpansionColumnNumber(Begin); 576 if (StartColNo) --StartColNo; // Zero base the col #. 577 } 578 579 // Compute the column number of the end. 580 unsigned EndColNo = CaretLine.size(); 581 if (EndLineNo == LineNo) { 582 EndColNo = SM.getExpansionColumnNumber(End); 583 if (EndColNo) { 584 --EndColNo; // Zero base the col #. 585 586 // Add in the length of the token, so that we cover multi-char tokens if 587 // this is a token range. 588 if (R.isTokenRange()) 589 EndColNo += Lexer::MeasureTokenLength(End, SM, LangOpts); 590 } else { 591 EndColNo = CaretLine.size(); 592 } 593 } 594 595 assert(StartColNo <= EndColNo && "Invalid range!"); 596 597 // Check that a token range does not highlight only whitespace. 598 if (R.isTokenRange()) { 599 // Pick the first non-whitespace column. 600 while (StartColNo < SourceLine.size() && 601 (SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t')) 602 ++StartColNo; 603 604 // Pick the last non-whitespace column. 605 if (EndColNo > SourceLine.size()) 606 EndColNo = SourceLine.size(); 607 while (EndColNo-1 && 608 (SourceLine[EndColNo-1] == ' ' || SourceLine[EndColNo-1] == '\t')) 609 --EndColNo; 610 611 // If the start/end passed each other, then we are trying to highlight a 612 // range that just exists in whitespace, which must be some sort of other 613 // bug. 614 assert(StartColNo <= EndColNo && "Trying to highlight whitespace??"); 615 } 616 617 // Fill the range with ~'s. 618 for (unsigned i = StartColNo; i < EndColNo; ++i) 619 CaretLine[i] = '~'; 620 } 621 622 std::string BuildFixItInsertionLine(unsigned LineNo, 623 const char *LineStart, 624 const char *LineEnd, 625 ArrayRef<FixItHint> Hints) { 626 std::string FixItInsertionLine; 627 if (Hints.empty() || !DiagOpts.ShowFixits) 628 return FixItInsertionLine; 629 630 for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end(); 631 I != E; ++I) { 632 if (!I->CodeToInsert.empty()) { 633 // We have an insertion hint. Determine whether the inserted 634 // code is on the same line as the caret. 635 std::pair<FileID, unsigned> HintLocInfo 636 = SM.getDecomposedExpansionLoc(I->RemoveRange.getBegin()); 637 if (LineNo == SM.getLineNumber(HintLocInfo.first, HintLocInfo.second)) { 638 // Insert the new code into the line just below the code 639 // that the user wrote. 640 unsigned HintColNo 641 = SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second); 642 unsigned LastColumnModified 643 = HintColNo - 1 + I->CodeToInsert.size(); 644 if (LastColumnModified > FixItInsertionLine.size()) 645 FixItInsertionLine.resize(LastColumnModified, ' '); 646 std::copy(I->CodeToInsert.begin(), I->CodeToInsert.end(), 647 FixItInsertionLine.begin() + HintColNo - 1); 648 } else { 649 FixItInsertionLine.clear(); 650 break; 651 } 652 } 653 } 654 655 if (FixItInsertionLine.empty()) 656 return FixItInsertionLine; 657 658 // Now that we have the entire fixit line, expand the tabs in it. 659 // Since we don't want to insert spaces in the middle of a word, 660 // find each word and the column it should line up with and insert 661 // spaces until they match. 662 unsigned FixItPos = 0; 663 unsigned LinePos = 0; 664 unsigned TabExpandedCol = 0; 665 unsigned LineLength = LineEnd - LineStart; 666 667 while (FixItPos < FixItInsertionLine.size() && LinePos < LineLength) { 668 // Find the next word in the FixIt line. 669 while (FixItPos < FixItInsertionLine.size() && 670 FixItInsertionLine[FixItPos] == ' ') 671 ++FixItPos; 672 unsigned CharDistance = FixItPos - TabExpandedCol; 673 674 // Walk forward in the source line, keeping track of 675 // the tab-expanded column. 676 for (unsigned I = 0; I < CharDistance; ++I, ++LinePos) 677 if (LinePos >= LineLength || LineStart[LinePos] != '\t') 678 ++TabExpandedCol; 679 else 680 TabExpandedCol = 681 (TabExpandedCol/DiagOpts.TabStop + 1) * DiagOpts.TabStop; 682 683 // Adjust the fixit line to match this column. 684 FixItInsertionLine.insert(FixItPos, TabExpandedCol-FixItPos, ' '); 685 FixItPos = TabExpandedCol; 686 687 // Walk to the end of the word. 688 while (FixItPos < FixItInsertionLine.size() && 689 FixItInsertionLine[FixItPos] != ' ') 690 ++FixItPos; 691 } 692 693 return FixItInsertionLine; 694 } 695 696 void ExpandTabs(std::string &SourceLine, std::string &CaretLine) { 697 // Scan the source line, looking for tabs. If we find any, manually expand 698 // them to spaces and update the CaretLine to match. 699 for (unsigned i = 0; i != SourceLine.size(); ++i) { 700 if (SourceLine[i] != '\t') continue; 701 702 // Replace this tab with at least one space. 703 SourceLine[i] = ' '; 704 705 // Compute the number of spaces we need to insert. 706 unsigned TabStop = DiagOpts.TabStop; 707 assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop && 708 "Invalid -ftabstop value"); 709 unsigned NumSpaces = ((i+TabStop)/TabStop * TabStop) - (i+1); 710 assert(NumSpaces < TabStop && "Invalid computation of space amt"); 711 712 // Insert spaces into the SourceLine. 713 SourceLine.insert(i+1, NumSpaces, ' '); 714 715 // Insert spaces or ~'s into CaretLine. 716 CaretLine.insert(i+1, NumSpaces, CaretLine[i] == '~' ? '~' : ' '); 717 } 718 } 719 720 void EmitParseableFixits(ArrayRef<FixItHint> Hints) { 721 if (!DiagOpts.ShowParseableFixits) 722 return; 723 724 // We follow FixItRewriter's example in not (yet) handling 725 // fix-its in macros. 726 for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end(); 727 I != E; ++I) { 728 if (I->RemoveRange.isInvalid() || 729 I->RemoveRange.getBegin().isMacroID() || 730 I->RemoveRange.getEnd().isMacroID()) 731 return; 732 } 733 734 for (ArrayRef<FixItHint>::iterator I = Hints.begin(), E = Hints.end(); 735 I != E; ++I) { 736 SourceLocation BLoc = I->RemoveRange.getBegin(); 737 SourceLocation ELoc = I->RemoveRange.getEnd(); 738 739 std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc); 740 std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc); 741 742 // Adjust for token ranges. 743 if (I->RemoveRange.isTokenRange()) 744 EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, LangOpts); 745 746 // We specifically do not do word-wrapping or tab-expansion here, 747 // because this is supposed to be easy to parse. 748 PresumedLoc PLoc = SM.getPresumedLoc(BLoc); 749 if (PLoc.isInvalid()) 750 break; 751 752 OS << "fix-it:\""; 753 OS.write_escaped(PLoc.getFilename()); 754 OS << "\":{" << SM.getLineNumber(BInfo.first, BInfo.second) 755 << ':' << SM.getColumnNumber(BInfo.first, BInfo.second) 756 << '-' << SM.getLineNumber(EInfo.first, EInfo.second) 757 << ':' << SM.getColumnNumber(EInfo.first, EInfo.second) 758 << "}:\""; 759 OS.write_escaped(I->CodeToInsert); 760 OS << "\"\n"; 761 } 762 } 763}; 764 765} // end namespace 766 767/// \brief Skip over whitespace in the string, starting at the given 768/// index. 769/// 770/// \returns The index of the first non-whitespace character that is 771/// greater than or equal to Idx or, if no such character exists, 772/// returns the end of the string. 773static unsigned skipWhitespace(unsigned Idx, 774 const SmallVectorImpl<char> &Str, 775 unsigned Length) { 776 while (Idx < Length && isspace(Str[Idx])) 777 ++Idx; 778 return Idx; 779} 780 781/// \brief If the given character is the start of some kind of 782/// balanced punctuation (e.g., quotes or parentheses), return the 783/// character that will terminate the punctuation. 784/// 785/// \returns The ending punctuation character, if any, or the NULL 786/// character if the input character does not start any punctuation. 787static inline char findMatchingPunctuation(char c) { 788 switch (c) { 789 case '\'': return '\''; 790 case '`': return '\''; 791 case '"': return '"'; 792 case '(': return ')'; 793 case '[': return ']'; 794 case '{': return '}'; 795 default: break; 796 } 797 798 return 0; 799} 800 801/// \brief Find the end of the word starting at the given offset 802/// within a string. 803/// 804/// \returns the index pointing one character past the end of the 805/// word. 806static unsigned findEndOfWord(unsigned Start, 807 const SmallVectorImpl<char> &Str, 808 unsigned Length, unsigned Column, 809 unsigned Columns) { 810 assert(Start < Str.size() && "Invalid start position!"); 811 unsigned End = Start + 1; 812 813 // If we are already at the end of the string, take that as the word. 814 if (End == Str.size()) 815 return End; 816 817 // Determine if the start of the string is actually opening 818 // punctuation, e.g., a quote or parentheses. 819 char EndPunct = findMatchingPunctuation(Str[Start]); 820 if (!EndPunct) { 821 // This is a normal word. Just find the first space character. 822 while (End < Length && !isspace(Str[End])) 823 ++End; 824 return End; 825 } 826 827 // We have the start of a balanced punctuation sequence (quotes, 828 // parentheses, etc.). Determine the full sequence is. 829 llvm::SmallString<16> PunctuationEndStack; 830 PunctuationEndStack.push_back(EndPunct); 831 while (End < Length && !PunctuationEndStack.empty()) { 832 if (Str[End] == PunctuationEndStack.back()) 833 PunctuationEndStack.pop_back(); 834 else if (char SubEndPunct = findMatchingPunctuation(Str[End])) 835 PunctuationEndStack.push_back(SubEndPunct); 836 837 ++End; 838 } 839 840 // Find the first space character after the punctuation ended. 841 while (End < Length && !isspace(Str[End])) 842 ++End; 843 844 unsigned PunctWordLength = End - Start; 845 if (// If the word fits on this line 846 Column + PunctWordLength <= Columns || 847 // ... or the word is "short enough" to take up the next line 848 // without too much ugly white space 849 PunctWordLength < Columns/3) 850 return End; // Take the whole thing as a single "word". 851 852 // The whole quoted/parenthesized string is too long to print as a 853 // single "word". Instead, find the "word" that starts just after 854 // the punctuation and use that end-point instead. This will recurse 855 // until it finds something small enough to consider a word. 856 return findEndOfWord(Start + 1, Str, Length, Column + 1, Columns); 857} 858 859/// Get the presumed location of a diagnostic message. This computes the 860/// presumed location for the top of any macro backtrace when present. 861static PresumedLoc getDiagnosticPresumedLoc(const SourceManager &SM, 862 SourceLocation Loc) { 863 // This is a condensed form of the algorithm used by EmitCaretDiagnostic to 864 // walk to the top of the macro call stack. 865 while (Loc.isMacroID()) { 866 Loc = skipToMacroArgExpansion(SM, Loc); 867 Loc = getImmediateMacroCallerLoc(SM, Loc); 868 } 869 870 return SM.getPresumedLoc(Loc); 871} 872 873/// \brief Print out the file/line/column information and include trace. 874/// 875/// This method handlen the emission of the diagnostic location information. 876/// This includes extracting as much location information as is present for the 877/// diagnostic and printing it, as well as any include stack or source ranges 878/// necessary. 879void TextDiagnosticPrinter::EmitDiagnosticLoc(DiagnosticsEngine::Level Level, 880 const Diagnostic &Info, 881 const SourceManager &SM, 882 PresumedLoc PLoc) { 883 if (PLoc.isInvalid()) { 884 // At least print the file name if available: 885 FileID FID = SM.getFileID(Info.getLocation()); 886 if (!FID.isInvalid()) { 887 const FileEntry* FE = SM.getFileEntryForID(FID); 888 if (FE && FE->getName()) { 889 OS << FE->getName(); 890 if (FE->getDevice() == 0 && FE->getInode() == 0 891 && FE->getFileMode() == 0) { 892 // in PCH is a guess, but a good one: 893 OS << " (in PCH)"; 894 } 895 OS << ": "; 896 } 897 } 898 return; 899 } 900 unsigned LineNo = PLoc.getLine(); 901 902 if (!DiagOpts->ShowLocation) 903 return; 904 905 if (DiagOpts->ShowColors) 906 OS.changeColor(savedColor, true); 907 908 OS << PLoc.getFilename(); 909 switch (DiagOpts->Format) { 910 case DiagnosticOptions::Clang: OS << ':' << LineNo; break; 911 case DiagnosticOptions::Msvc: OS << '(' << LineNo; break; 912 case DiagnosticOptions::Vi: OS << " +" << LineNo; break; 913 } 914 915 if (DiagOpts->ShowColumn) 916 // Compute the column number. 917 if (unsigned ColNo = PLoc.getColumn()) { 918 if (DiagOpts->Format == DiagnosticOptions::Msvc) { 919 OS << ','; 920 ColNo--; 921 } else 922 OS << ':'; 923 OS << ColNo; 924 } 925 switch (DiagOpts->Format) { 926 case DiagnosticOptions::Clang: 927 case DiagnosticOptions::Vi: OS << ':'; break; 928 case DiagnosticOptions::Msvc: OS << ") : "; break; 929 } 930 931 if (DiagOpts->ShowSourceRanges && Info.getNumRanges()) { 932 FileID CaretFileID = 933 SM.getFileID(SM.getExpansionLoc(Info.getLocation())); 934 bool PrintedRange = false; 935 936 for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i) { 937 // Ignore invalid ranges. 938 if (!Info.getRange(i).isValid()) continue; 939 940 SourceLocation B = Info.getRange(i).getBegin(); 941 SourceLocation E = Info.getRange(i).getEnd(); 942 B = SM.getExpansionLoc(B); 943 E = SM.getExpansionLoc(E); 944 945 // If the End location and the start location are the same and are a 946 // macro location, then the range was something that came from a 947 // macro expansion or _Pragma. If this is an object-like macro, the 948 // best we can do is to highlight the range. If this is a 949 // function-like macro, we'd also like to highlight the arguments. 950 if (B == E && Info.getRange(i).getEnd().isMacroID()) 951 E = SM.getExpansionRange(Info.getRange(i).getEnd()).second; 952 953 std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B); 954 std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E); 955 956 // If the start or end of the range is in another file, just discard 957 // it. 958 if (BInfo.first != CaretFileID || EInfo.first != CaretFileID) 959 continue; 960 961 // Add in the length of the token, so that we cover multi-char 962 // tokens. 963 unsigned TokSize = 0; 964 if (Info.getRange(i).isTokenRange()) 965 TokSize = Lexer::MeasureTokenLength(E, SM, *LangOpts); 966 967 OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':' 968 << SM.getColumnNumber(BInfo.first, BInfo.second) << '-' 969 << SM.getLineNumber(EInfo.first, EInfo.second) << ':' 970 << (SM.getColumnNumber(EInfo.first, EInfo.second)+TokSize) 971 << '}'; 972 PrintedRange = true; 973 } 974 975 if (PrintedRange) 976 OS << ':'; 977 } 978 OS << ' '; 979} 980 981/// \brief Print the diagonstic level to a raw_ostream. 982/// 983/// Handles colorizing the level and formatting. 984static void printDiagnosticLevel(raw_ostream &OS, 985 DiagnosticsEngine::Level Level, 986 bool ShowColors) { 987 if (ShowColors) { 988 // Print diagnostic category in bold and color 989 switch (Level) { 990 case DiagnosticsEngine::Ignored: 991 llvm_unreachable("Invalid diagnostic type"); 992 case DiagnosticsEngine::Note: OS.changeColor(noteColor, true); break; 993 case DiagnosticsEngine::Warning: OS.changeColor(warningColor, true); break; 994 case DiagnosticsEngine::Error: OS.changeColor(errorColor, true); break; 995 case DiagnosticsEngine::Fatal: OS.changeColor(fatalColor, true); break; 996 } 997 } 998 999 switch (Level) { 1000 case DiagnosticsEngine::Ignored: llvm_unreachable("Invalid diagnostic type"); 1001 case DiagnosticsEngine::Note: OS << "note: "; break; 1002 case DiagnosticsEngine::Warning: OS << "warning: "; break; 1003 case DiagnosticsEngine::Error: OS << "error: "; break; 1004 case DiagnosticsEngine::Fatal: OS << "fatal error: "; break; 1005 } 1006 1007 if (ShowColors) 1008 OS.resetColor(); 1009} 1010 1011/// \brief Print the diagnostic name to a raw_ostream. 1012/// 1013/// This prints the diagnostic name to a raw_ostream if it has one. It formats 1014/// the name according to the expected diagnostic message formatting: 1015/// " [diagnostic_name_here]" 1016static void printDiagnosticName(raw_ostream &OS, const Diagnostic &Info) { 1017 if (!DiagnosticIDs::isBuiltinNote(Info.getID())) 1018 OS << " [" << DiagnosticIDs::getName(Info.getID()) << "]"; 1019} 1020 1021/// \brief Print any diagnostic option information to a raw_ostream. 1022/// 1023/// This implements all of the logic for adding diagnostic options to a message 1024/// (via OS). Each relevant option is comma separated and all are enclosed in 1025/// the standard bracketing: " [...]". 1026static void printDiagnosticOptions(raw_ostream &OS, 1027 DiagnosticsEngine::Level Level, 1028 const Diagnostic &Info, 1029 const DiagnosticOptions &DiagOpts) { 1030 bool Started = false; 1031 if (DiagOpts.ShowOptionNames) { 1032 // Handle special cases for non-warnings early. 1033 if (Info.getID() == diag::fatal_too_many_errors) { 1034 OS << " [-ferror-limit=]"; 1035 return; 1036 } 1037 1038 // Was this a warning mapped to an error using -Werror or pragma? 1039 if (Level == DiagnosticsEngine::Error && 1040 DiagnosticIDs::isBuiltinWarningOrExtension(Info.getID())) { 1041 diag::Mapping mapping = diag::MAP_IGNORE; 1042 Info.getDiags()->getDiagnosticLevel(Info.getID(), Info.getLocation(), 1043 &mapping); 1044 if (mapping == diag::MAP_WARNING) { 1045 OS << " [-Werror"; 1046 Started = true; 1047 } 1048 } 1049 1050 // If the diagnostic is an extension diagnostic and not enabled by default 1051 // then it must have been turned on with -pedantic. 1052 bool EnabledByDefault; 1053 if (DiagnosticIDs::isBuiltinExtensionDiag(Info.getID(), 1054 EnabledByDefault) && 1055 !EnabledByDefault) { 1056 OS << (Started ? "," : " [") << "-pedantic"; 1057 Started = true; 1058 } 1059 1060 StringRef Opt = DiagnosticIDs::getWarningOptionForDiag(Info.getID()); 1061 if (!Opt.empty()) { 1062 OS << (Started ? "," : " [") << "-W" << Opt; 1063 Started = true; 1064 } 1065 } 1066 1067 // If the user wants to see category information, include it too. 1068 if (DiagOpts.ShowCategories) { 1069 unsigned DiagCategory = 1070 DiagnosticIDs::getCategoryNumberForDiag(Info.getID()); 1071 if (DiagCategory) { 1072 OS << (Started ? "," : " ["); 1073 if (DiagOpts.ShowCategories == 1) 1074 OS << llvm::utostr(DiagCategory); 1075 else { 1076 assert(DiagOpts.ShowCategories == 2 && "Invalid ShowCategories value"); 1077 OS << DiagnosticIDs::getCategoryNameFromID(DiagCategory); 1078 } 1079 } 1080 } 1081 OS << "]"; 1082} 1083 1084/// \brief Print the given string to a stream, word-wrapping it to 1085/// some number of columns in the process. 1086/// 1087/// \param OS the stream to which the word-wrapping string will be 1088/// emitted. 1089/// \param Str the string to word-wrap and output. 1090/// \param Columns the number of columns to word-wrap to. 1091/// \param Column the column number at which the first character of \p 1092/// Str will be printed. This will be non-zero when part of the first 1093/// line has already been printed. 1094/// \param Indentation the number of spaces to indent any lines beyond 1095/// the first line. 1096/// \returns true if word-wrapping was required, or false if the 1097/// string fit on the first line. 1098static bool printWordWrapped(raw_ostream &OS, 1099 const SmallVectorImpl<char> &Str, 1100 unsigned Columns, 1101 unsigned Column = 0, 1102 unsigned Indentation = WordWrapIndentation) { 1103 unsigned Length = Str.size(); 1104 1105 // If there is a newline in this message somewhere, find that 1106 // newline and split the message into the part before the newline 1107 // (which will be word-wrapped) and the part from the newline one 1108 // (which will be emitted unchanged). 1109 for (unsigned I = 0; I != Length; ++I) 1110 if (Str[I] == '\n') { 1111 Length = I; 1112 break; 1113 } 1114 1115 // The string used to indent each line. 1116 llvm::SmallString<16> IndentStr; 1117 IndentStr.assign(Indentation, ' '); 1118 bool Wrapped = false; 1119 for (unsigned WordStart = 0, WordEnd; WordStart < Length; 1120 WordStart = WordEnd) { 1121 // Find the beginning of the next word. 1122 WordStart = skipWhitespace(WordStart, Str, Length); 1123 if (WordStart == Length) 1124 break; 1125 1126 // Find the end of this word. 1127 WordEnd = findEndOfWord(WordStart, Str, Length, Column, Columns); 1128 1129 // Does this word fit on the current line? 1130 unsigned WordLength = WordEnd - WordStart; 1131 if (Column + WordLength < Columns) { 1132 // This word fits on the current line; print it there. 1133 if (WordStart) { 1134 OS << ' '; 1135 Column += 1; 1136 } 1137 OS.write(&Str[WordStart], WordLength); 1138 Column += WordLength; 1139 continue; 1140 } 1141 1142 // This word does not fit on the current line, so wrap to the next 1143 // line. 1144 OS << '\n'; 1145 OS.write(&IndentStr[0], Indentation); 1146 OS.write(&Str[WordStart], WordLength); 1147 Column = Indentation + WordLength; 1148 Wrapped = true; 1149 } 1150 1151 if (Length == Str.size()) 1152 return Wrapped; // We're done. 1153 1154 // There is a newline in the message, followed by something that 1155 // will not be word-wrapped. Print that. 1156 OS.write(&Str[Length], Str.size() - Length); 1157 return true; 1158} 1159 1160void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level, 1161 const Diagnostic &Info) { 1162 // Default implementation (Warnings/errors count). 1163 DiagnosticConsumer::HandleDiagnostic(Level, Info); 1164 1165 // Keeps track of the the starting position of the location 1166 // information (e.g., "foo.c:10:4:") that precedes the error 1167 // message. We use this information to determine how long the 1168 // file+line+column number prefix is. 1169 uint64_t StartOfLocationInfo = OS.tell(); 1170 1171 if (!Prefix.empty()) 1172 OS << Prefix << ": "; 1173 1174 if (Info.getLocation().isValid()) { 1175 const SourceManager &SM = Info.getSourceManager(); 1176 PresumedLoc PLoc = getDiagnosticPresumedLoc(SM, Info.getLocation()); 1177 1178 // First, if this diagnostic is not in the main file, print out the 1179 // "included from" lines. 1180 PrintIncludeStack(Level, PLoc.getIncludeLoc(), SM); 1181 StartOfLocationInfo = OS.tell(); 1182 1183 // Next emit the location of this particular diagnostic. 1184 EmitDiagnosticLoc(Level, Info, SM, PLoc); 1185 1186 if (DiagOpts->ShowColors) 1187 OS.resetColor(); 1188 } 1189 1190 printDiagnosticLevel(OS, Level, DiagOpts->ShowColors); 1191 1192 llvm::SmallString<100> OutStr; 1193 Info.FormatDiagnostic(OutStr); 1194 1195 llvm::raw_svector_ostream DiagMessageStream(OutStr); 1196 if (DiagOpts->ShowNames) 1197 printDiagnosticName(DiagMessageStream, Info); 1198 printDiagnosticOptions(DiagMessageStream, Level, Info, *DiagOpts); 1199 DiagMessageStream.flush(); 1200 1201 if (DiagOpts->ShowColors) { 1202 // Print warnings, errors and fatal errors in bold, no color 1203 switch (Level) { 1204 case DiagnosticsEngine::Warning: OS.changeColor(savedColor, true); break; 1205 case DiagnosticsEngine::Error: OS.changeColor(savedColor, true); break; 1206 case DiagnosticsEngine::Fatal: OS.changeColor(savedColor, true); break; 1207 default: break; //don't bold notes 1208 } 1209 } 1210 1211 if (DiagOpts->MessageLength) { 1212 // We will be word-wrapping the error message, so compute the 1213 // column number where we currently are (after printing the 1214 // location information). 1215 unsigned Column = OS.tell() - StartOfLocationInfo; 1216 printWordWrapped(OS, OutStr, DiagOpts->MessageLength, Column); 1217 } else { 1218 OS.write(OutStr.begin(), OutStr.size()); 1219 } 1220 OS << '\n'; 1221 if (DiagOpts->ShowColors) 1222 OS.resetColor(); 1223 1224 // If caret diagnostics are enabled and we have location, we want to 1225 // emit the caret. However, we only do this if the location moved 1226 // from the last diagnostic, if the last diagnostic was a note that 1227 // was part of a different warning or error diagnostic, or if the 1228 // diagnostic has ranges. We don't want to emit the same caret 1229 // multiple times if one loc has multiple diagnostics. 1230 if (DiagOpts->ShowCarets && Info.getLocation().isValid() && 1231 ((LastLoc != Info.getLocation()) || Info.getNumRanges() || 1232 (LastCaretDiagnosticWasNote && Level != DiagnosticsEngine::Note) || 1233 Info.getNumFixItHints())) { 1234 // Cache the LastLoc, it allows us to omit duplicate source/caret spewage. 1235 LastLoc = FullSourceLoc(Info.getLocation(), Info.getSourceManager()); 1236 LastCaretDiagnosticWasNote = (Level == DiagnosticsEngine::Note); 1237 1238 // Get the ranges into a local array we can hack on. 1239 SmallVector<CharSourceRange, 20> Ranges; 1240 Ranges.reserve(Info.getNumRanges()); 1241 for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i) 1242 Ranges.push_back(Info.getRange(i)); 1243 1244 for (unsigned i = 0, e = Info.getNumFixItHints(); i != e; ++i) { 1245 const FixItHint &Hint = Info.getFixItHint(i); 1246 if (Hint.RemoveRange.isValid()) 1247 Ranges.push_back(Hint.RemoveRange); 1248 } 1249 1250 assert(LangOpts && "Unexpected diagnostic outside source file processing"); 1251 assert(DiagOpts && "Unexpected diagnostic without options set"); 1252 1253 TextDiagnostic TextDiag(*this, OS, Info.getSourceManager(), 1254 *LangOpts, *DiagOpts); 1255 unsigned MacroDepth = 0; 1256 TextDiag.Emit(LastLoc, Ranges, llvm::makeArrayRef(Info.getFixItHints(), 1257 Info.getNumFixItHints()), 1258 MacroDepth); 1259 } 1260 1261 OS.flush(); 1262} 1263