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