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