]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/Frontend/TextDiagnosticPrinter.cpp
Upgrade our copy of llvm/clang to r132879, from upstream's trunk.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / Frontend / TextDiagnosticPrinter.cpp
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/ADT/SmallString.h"
22 #include "llvm/ADT/StringExtras.h"
23 #include <algorithm>
24 using namespace clang;
25
26 static const enum llvm::raw_ostream::Colors noteColor =
27   llvm::raw_ostream::BLACK;
28 static const enum llvm::raw_ostream::Colors fixitColor =
29   llvm::raw_ostream::GREEN;
30 static const enum llvm::raw_ostream::Colors caretColor =
31   llvm::raw_ostream::GREEN;
32 static const enum llvm::raw_ostream::Colors warningColor =
33   llvm::raw_ostream::MAGENTA;
34 static const enum llvm::raw_ostream::Colors errorColor = llvm::raw_ostream::RED;
35 static const enum llvm::raw_ostream::Colors fatalColor = llvm::raw_ostream::RED;
36 // Used for changing only the bold attribute.
37 static const enum llvm::raw_ostream::Colors savedColor =
38   llvm::raw_ostream::SAVEDCOLOR;
39
40 /// \brief Number of spaces to indent when word-wrapping.
41 const unsigned WordWrapIndentation = 6;
42
43 TextDiagnosticPrinter::TextDiagnosticPrinter(llvm::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
51 TextDiagnosticPrinter::~TextDiagnosticPrinter() {
52   if (OwnsOutputStream)
53     delete &OS;
54 }
55
56 void TextDiagnosticPrinter::PrintIncludeStack(Diagnostic::Level Level,
57                                               SourceLocation Loc,
58                                               const SourceManager &SM) {
59   if (!DiagOpts->ShowNoteIncludeStack && Level == Diagnostic::Note) return;
60
61   if (Loc.isInvalid()) return;
62
63   PresumedLoc PLoc = SM.getPresumedLoc(Loc);
64   if (PLoc.isInvalid())
65     return;
66   
67   // Print out the other include frames first.
68   PrintIncludeStack(Level, PLoc.getIncludeLoc(), SM);
69
70   if (DiagOpts->ShowLocation)
71     OS << "In file included from " << PLoc.getFilename()
72        << ':' << PLoc.getLine() << ":\n";
73   else
74     OS << "In included file:\n";
75 }
76
77 /// HighlightRange - Given a SourceRange and a line number, highlight (with ~'s)
78 /// any characters in LineNo that intersect the SourceRange.
79 void TextDiagnosticPrinter::HighlightRange(const CharSourceRange &R,
80                                            const SourceManager &SM,
81                                            unsigned LineNo, FileID FID,
82                                            std::string &CaretLine,
83                                            const std::string &SourceLine) {
84   assert(CaretLine.size() == SourceLine.size() &&
85          "Expect a correspondence between source and caret line!");
86   if (!R.isValid()) return;
87
88   SourceLocation Begin = SM.getInstantiationLoc(R.getBegin());
89   SourceLocation End = SM.getInstantiationLoc(R.getEnd());
90
91   // If the End location and the start location are the same and are a macro
92   // location, then the range was something that came from a macro expansion
93   // or _Pragma.  If this is an object-like macro, the best we can do is to
94   // highlight the range.  If this is a function-like macro, we'd also like to
95   // highlight the arguments.
96   if (Begin == End && R.getEnd().isMacroID())
97     End = SM.getInstantiationRange(R.getEnd()).second;
98
99   unsigned StartLineNo = SM.getInstantiationLineNumber(Begin);
100   if (StartLineNo > LineNo || SM.getFileID(Begin) != FID)
101     return;  // No intersection.
102
103   unsigned EndLineNo = SM.getInstantiationLineNumber(End);
104   if (EndLineNo < LineNo || SM.getFileID(End) != FID)
105     return;  // No intersection.
106
107   // Compute the column number of the start.
108   unsigned StartColNo = 0;
109   if (StartLineNo == LineNo) {
110     StartColNo = SM.getInstantiationColumnNumber(Begin);
111     if (StartColNo) --StartColNo;  // Zero base the col #.
112   }
113
114   // Compute the column number of the end.
115   unsigned EndColNo = CaretLine.size();
116   if (EndLineNo == LineNo) {
117     EndColNo = SM.getInstantiationColumnNumber(End);
118     if (EndColNo) {
119       --EndColNo;  // Zero base the col #.
120
121       // Add in the length of the token, so that we cover multi-char tokens if
122       // this is a token range.
123       if (R.isTokenRange())
124         EndColNo += Lexer::MeasureTokenLength(End, SM, *LangOpts);
125     } else {
126       EndColNo = CaretLine.size();
127     }
128   }
129
130   assert(StartColNo <= EndColNo && "Invalid range!");
131
132   // Check that a token range does not highlight only whitespace.
133   if (R.isTokenRange()) {
134     // Pick the first non-whitespace column.
135     while (StartColNo < SourceLine.size() &&
136            (SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t'))
137       ++StartColNo;
138
139     // Pick the last non-whitespace column.
140     if (EndColNo > SourceLine.size())
141       EndColNo = SourceLine.size();
142     while (EndColNo-1 &&
143            (SourceLine[EndColNo-1] == ' ' || SourceLine[EndColNo-1] == '\t'))
144       --EndColNo;
145
146     // If the start/end passed each other, then we are trying to highlight a
147     // range that just exists in whitespace, which must be some sort of other
148     // bug.
149     assert(StartColNo <= EndColNo && "Trying to highlight whitespace??");
150   }
151
152   // Fill the range with ~'s.
153   for (unsigned i = StartColNo; i < EndColNo; ++i)
154     CaretLine[i] = '~';
155 }
156
157 /// \brief When the source code line we want to print is too long for
158 /// the terminal, select the "interesting" region.
159 static void SelectInterestingSourceRegion(std::string &SourceLine,
160                                           std::string &CaretLine,
161                                           std::string &FixItInsertionLine,
162                                           unsigned EndOfCaretToken,
163                                           unsigned Columns) {
164   unsigned MaxSize = std::max(SourceLine.size(),
165                               std::max(CaretLine.size(), 
166                                        FixItInsertionLine.size()));
167   if (MaxSize > SourceLine.size())
168     SourceLine.resize(MaxSize, ' ');
169   if (MaxSize > CaretLine.size())
170     CaretLine.resize(MaxSize, ' ');
171   if (!FixItInsertionLine.empty() && MaxSize > FixItInsertionLine.size())
172     FixItInsertionLine.resize(MaxSize, ' ');
173     
174   // Find the slice that we need to display the full caret line
175   // correctly.
176   unsigned CaretStart = 0, CaretEnd = CaretLine.size();
177   for (; CaretStart != CaretEnd; ++CaretStart)
178     if (!isspace(CaretLine[CaretStart]))
179       break;
180
181   for (; CaretEnd != CaretStart; --CaretEnd)
182     if (!isspace(CaretLine[CaretEnd - 1]))
183       break;
184
185   // Make sure we don't chop the string shorter than the caret token
186   // itself.
187   if (CaretEnd < EndOfCaretToken)
188     CaretEnd = EndOfCaretToken;
189
190   // If we have a fix-it line, make sure the slice includes all of the
191   // fix-it information.
192   if (!FixItInsertionLine.empty()) {
193     unsigned FixItStart = 0, FixItEnd = FixItInsertionLine.size();
194     for (; FixItStart != FixItEnd; ++FixItStart)
195       if (!isspace(FixItInsertionLine[FixItStart]))
196         break;
197
198     for (; FixItEnd != FixItStart; --FixItEnd)
199       if (!isspace(FixItInsertionLine[FixItEnd - 1]))
200         break;
201
202     if (FixItStart < CaretStart)
203       CaretStart = FixItStart;
204     if (FixItEnd > CaretEnd)
205       CaretEnd = FixItEnd;
206   }
207
208   // CaretLine[CaretStart, CaretEnd) contains all of the interesting
209   // parts of the caret line. While this slice is smaller than the
210   // number of columns we have, try to grow the slice to encompass
211   // more context.
212
213   // If the end of the interesting region comes before we run out of
214   // space in the terminal, start at the beginning of the line.
215   if (Columns > 3 && CaretEnd < Columns - 3)
216     CaretStart = 0;
217
218   unsigned TargetColumns = Columns;
219   if (TargetColumns > 8)
220     TargetColumns -= 8; // Give us extra room for the ellipses.
221   unsigned SourceLength = SourceLine.size();
222   while ((CaretEnd - CaretStart) < TargetColumns) {
223     bool ExpandedRegion = false;
224     // Move the start of the interesting region left until we've
225     // pulled in something else interesting.
226     if (CaretStart == 1)
227       CaretStart = 0;
228     else if (CaretStart > 1) {
229       unsigned NewStart = CaretStart - 1;
230
231       // Skip over any whitespace we see here; we're looking for
232       // another bit of interesting text.
233       while (NewStart && isspace(SourceLine[NewStart]))
234         --NewStart;
235
236       // Skip over this bit of "interesting" text.
237       while (NewStart && !isspace(SourceLine[NewStart]))
238         --NewStart;
239
240       // Move up to the non-whitespace character we just saw.
241       if (NewStart)
242         ++NewStart;
243
244       // If we're still within our limit, update the starting
245       // position within the source/caret line.
246       if (CaretEnd - NewStart <= TargetColumns) {
247         CaretStart = NewStart;
248         ExpandedRegion = true;
249       }
250     }
251
252     // Move the end of the interesting region right until we've
253     // pulled in something else interesting.
254     if (CaretEnd != SourceLength) {
255       assert(CaretEnd < SourceLength && "Unexpected caret position!");
256       unsigned NewEnd = CaretEnd;
257
258       // Skip over any whitespace we see here; we're looking for
259       // another bit of interesting text.
260       while (NewEnd != SourceLength && isspace(SourceLine[NewEnd - 1]))
261         ++NewEnd;
262
263       // Skip over this bit of "interesting" text.
264       while (NewEnd != SourceLength && !isspace(SourceLine[NewEnd - 1]))
265         ++NewEnd;
266
267       if (NewEnd - CaretStart <= TargetColumns) {
268         CaretEnd = NewEnd;
269         ExpandedRegion = true;
270       }
271     }
272
273     if (!ExpandedRegion)
274       break;
275   }
276
277   // [CaretStart, CaretEnd) is the slice we want. Update the various
278   // output lines to show only this slice, with two-space padding
279   // before the lines so that it looks nicer.
280   if (CaretEnd < SourceLine.size())
281     SourceLine.replace(CaretEnd, std::string::npos, "...");
282   if (CaretEnd < CaretLine.size())
283     CaretLine.erase(CaretEnd, std::string::npos);
284   if (FixItInsertionLine.size() > CaretEnd)
285     FixItInsertionLine.erase(CaretEnd, std::string::npos);
286
287   if (CaretStart > 2) {
288     SourceLine.replace(0, CaretStart, "  ...");
289     CaretLine.replace(0, CaretStart, "     ");
290     if (FixItInsertionLine.size() >= CaretStart)
291       FixItInsertionLine.replace(0, CaretStart, "     ");
292   }
293 }
294
295 void TextDiagnosticPrinter::EmitCaretDiagnostic(Diagnostic::Level Level,
296                                                 SourceLocation Loc,
297                                                 CharSourceRange *Ranges,
298                                                 unsigned NumRanges,
299                                                 const SourceManager &SM,
300                                                 const FixItHint *Hints,
301                                                 unsigned NumHints,
302                                                 unsigned Columns,  
303                                                 unsigned OnMacroInst,
304                                                 unsigned MacroSkipStart,
305                                                 unsigned MacroSkipEnd) {
306   assert(LangOpts && "Unexpected diagnostic outside source file processing");
307   assert(!Loc.isInvalid() && "must have a valid source location here");
308
309   // If this is a macro ID, first emit information about where this was
310   // instantiated (recursively) then emit information about where the token was
311   // spelled from.
312   if (!Loc.isFileID()) {
313     // Whether to suppress printing this macro instantiation.
314     bool Suppressed 
315       = OnMacroInst >= MacroSkipStart && OnMacroInst < MacroSkipEnd;
316     
317
318     SourceLocation OneLevelUp = SM.getImmediateInstantiationRange(Loc).first;
319     // FIXME: Map ranges?
320     EmitCaretDiagnostic(Level, OneLevelUp, Ranges, NumRanges, SM, 0, 0, Columns,
321                         OnMacroInst + 1, MacroSkipStart, MacroSkipEnd);
322     
323     // Map the location.
324     Loc = SM.getImmediateSpellingLoc(Loc);
325
326     // Map the ranges.
327     for (unsigned i = 0; i != NumRanges; ++i) {
328       CharSourceRange &R = Ranges[i];
329       SourceLocation S = R.getBegin(), E = R.getEnd();
330       if (S.isMacroID())
331         R.setBegin(SM.getImmediateSpellingLoc(S));
332       if (E.isMacroID())
333         R.setEnd(SM.getImmediateSpellingLoc(E));
334     }
335
336     if (!Suppressed) {
337       // Get the pretty name, according to #line directives etc.
338       PresumedLoc PLoc = SM.getPresumedLoc(Loc);
339       if (PLoc.isInvalid())
340         return;
341       
342       // If this diagnostic is not in the main file, print out the
343       // "included from" lines.
344       if (LastWarningLoc != PLoc.getIncludeLoc()) {
345         LastWarningLoc = PLoc.getIncludeLoc();
346         PrintIncludeStack(Diagnostic::Note, LastWarningLoc, SM);
347       }
348
349       if (DiagOpts->ShowLocation) {
350         // Emit the file/line/column that this expansion came from.
351         OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':';
352         if (DiagOpts->ShowColumn)
353           OS << PLoc.getColumn() << ':';
354         OS << ' ';
355       }
356       OS << "note: instantiated from:\n";
357       
358       EmitCaretDiagnostic(Level, Loc, Ranges, NumRanges, SM, Hints, NumHints,
359                           Columns, OnMacroInst + 1, MacroSkipStart,
360                           MacroSkipEnd);
361       return;
362     }
363     
364     if (OnMacroInst == MacroSkipStart) {
365       // Tell the user that we've skipped contexts.
366       OS << "note: (skipping " << (MacroSkipEnd - MacroSkipStart) 
367       << " contexts in backtrace; use -fmacro-backtrace-limit=0 to see "
368       "all)\n";
369     }
370     
371     return;
372   }
373
374   // Decompose the location into a FID/Offset pair.
375   std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
376   FileID FID = LocInfo.first;
377   unsigned FileOffset = LocInfo.second;
378
379   // Get information about the buffer it points into.
380   bool Invalid = false;
381   const char *BufStart = SM.getBufferData(FID, &Invalid).data();
382   if (Invalid)
383     return;
384
385   unsigned ColNo = SM.getColumnNumber(FID, FileOffset);
386   unsigned CaretEndColNo
387     = ColNo + Lexer::MeasureTokenLength(Loc, SM, *LangOpts);
388
389   // Rewind from the current position to the start of the line.
390   const char *TokPtr = BufStart+FileOffset;
391   const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based.
392
393
394   // Compute the line end.  Scan forward from the error position to the end of
395   // the line.
396   const char *LineEnd = TokPtr;
397   while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')
398     ++LineEnd;
399
400   // FIXME: This shouldn't be necessary, but the CaretEndColNo can extend past
401   // the source line length as currently being computed. See
402   // test/Misc/message-length.c.
403   CaretEndColNo = std::min(CaretEndColNo, unsigned(LineEnd - LineStart));
404
405   // Copy the line of code into an std::string for ease of manipulation.
406   std::string SourceLine(LineStart, LineEnd);
407
408   // Create a line for the caret that is filled with spaces that is the same
409   // length as the line of source code.
410   std::string CaretLine(LineEnd-LineStart, ' ');
411
412   // Highlight all of the characters covered by Ranges with ~ characters.
413   if (NumRanges) {
414     unsigned LineNo = SM.getLineNumber(FID, FileOffset);
415
416     for (unsigned i = 0, e = NumRanges; i != e; ++i)
417       HighlightRange(Ranges[i], SM, LineNo, FID, CaretLine, SourceLine);
418   }
419
420   // Next, insert the caret itself.
421   if (ColNo-1 < CaretLine.size())
422     CaretLine[ColNo-1] = '^';
423   else
424     CaretLine.push_back('^');
425
426   // Scan the source line, looking for tabs.  If we find any, manually expand
427   // them to spaces and update the CaretLine to match.
428   for (unsigned i = 0; i != SourceLine.size(); ++i) {
429     if (SourceLine[i] != '\t') continue;
430
431     // Replace this tab with at least one space.
432     SourceLine[i] = ' ';
433
434     // Compute the number of spaces we need to insert.
435     unsigned TabStop = DiagOpts->TabStop;
436     assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop &&
437            "Invalid -ftabstop value");
438     unsigned NumSpaces = ((i+TabStop)/TabStop * TabStop) - (i+1);
439     assert(NumSpaces < TabStop && "Invalid computation of space amt");
440
441     // Insert spaces into the SourceLine.
442     SourceLine.insert(i+1, NumSpaces, ' ');
443
444     // Insert spaces or ~'s into CaretLine.
445     CaretLine.insert(i+1, NumSpaces, CaretLine[i] == '~' ? '~' : ' ');
446   }
447
448   // If we are in -fdiagnostics-print-source-range-info mode, we are trying to
449   // produce easily machine parsable output.  Add a space before the source line
450   // and the caret to make it trivial to tell the main diagnostic line from what
451   // the user is intended to see.
452   if (DiagOpts->ShowSourceRanges) {
453     SourceLine = ' ' + SourceLine;
454     CaretLine = ' ' + CaretLine;
455   }
456
457   std::string FixItInsertionLine;
458   if (NumHints && DiagOpts->ShowFixits) {
459     for (const FixItHint *Hint = Hints, *LastHint = Hints + NumHints;
460          Hint != LastHint; ++Hint) {
461       if (!Hint->CodeToInsert.empty()) {
462         // We have an insertion hint. Determine whether the inserted
463         // code is on the same line as the caret.
464         std::pair<FileID, unsigned> HintLocInfo
465           = SM.getDecomposedInstantiationLoc(Hint->RemoveRange.getBegin());
466         if (SM.getLineNumber(HintLocInfo.first, HintLocInfo.second) ==
467               SM.getLineNumber(FID, FileOffset)) {
468           // Insert the new code into the line just below the code
469           // that the user wrote.
470           unsigned HintColNo
471             = SM.getColumnNumber(HintLocInfo.first, HintLocInfo.second);
472           unsigned LastColumnModified
473             = HintColNo - 1 + Hint->CodeToInsert.size();
474           if (LastColumnModified > FixItInsertionLine.size())
475             FixItInsertionLine.resize(LastColumnModified, ' ');
476           std::copy(Hint->CodeToInsert.begin(), Hint->CodeToInsert.end(),
477                     FixItInsertionLine.begin() + HintColNo - 1);
478         } else {
479           FixItInsertionLine.clear();
480           break;
481         }
482       }
483     }
484     // Now that we have the entire fixit line, expand the tabs in it.
485     // Since we don't want to insert spaces in the middle of a word,
486     // find each word and the column it should line up with and insert
487     // spaces until they match.
488     if (!FixItInsertionLine.empty()) {
489       unsigned FixItPos = 0;
490       unsigned LinePos = 0;
491       unsigned TabExpandedCol = 0;
492       unsigned LineLength = LineEnd - LineStart;
493
494       while (FixItPos < FixItInsertionLine.size() && LinePos < LineLength) {
495         // Find the next word in the FixIt line.
496         while (FixItPos < FixItInsertionLine.size() &&
497                FixItInsertionLine[FixItPos] == ' ')
498           ++FixItPos;
499         unsigned CharDistance = FixItPos - TabExpandedCol;
500
501         // Walk forward in the source line, keeping track of
502         // the tab-expanded column.
503         for (unsigned I = 0; I < CharDistance; ++I, ++LinePos)
504           if (LinePos >= LineLength || LineStart[LinePos] != '\t')
505             ++TabExpandedCol;
506           else
507             TabExpandedCol =
508               (TabExpandedCol/DiagOpts->TabStop + 1) * DiagOpts->TabStop;
509
510         // Adjust the fixit line to match this column.
511         FixItInsertionLine.insert(FixItPos, TabExpandedCol-FixItPos, ' ');
512         FixItPos = TabExpandedCol;
513
514         // Walk to the end of the word.
515         while (FixItPos < FixItInsertionLine.size() &&
516                FixItInsertionLine[FixItPos] != ' ')
517           ++FixItPos;
518       }
519     }
520   }
521
522   // If the source line is too long for our terminal, select only the
523   // "interesting" source region within that line.
524   if (Columns && SourceLine.size() > Columns)
525     SelectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine,
526                                   CaretEndColNo, Columns);
527
528   // Finally, remove any blank spaces from the end of CaretLine.
529   while (CaretLine[CaretLine.size()-1] == ' ')
530     CaretLine.erase(CaretLine.end()-1);
531
532   // Emit what we have computed.
533   OS << SourceLine << '\n';
534
535   if (DiagOpts->ShowColors)
536     OS.changeColor(caretColor, true);
537   OS << CaretLine << '\n';
538   if (DiagOpts->ShowColors)
539     OS.resetColor();
540
541   if (!FixItInsertionLine.empty()) {
542     if (DiagOpts->ShowColors)
543       // Print fixit line in color
544       OS.changeColor(fixitColor, false);
545     if (DiagOpts->ShowSourceRanges)
546       OS << ' ';
547     OS << FixItInsertionLine << '\n';
548     if (DiagOpts->ShowColors)
549       OS.resetColor();
550   }
551
552   if (DiagOpts->ShowParseableFixits) {
553
554     // We follow FixItRewriter's example in not (yet) handling
555     // fix-its in macros.
556     bool BadApples = false;
557     for (const FixItHint *Hint = Hints; Hint != Hints + NumHints; ++Hint) {
558       if (Hint->RemoveRange.isInvalid() ||
559           Hint->RemoveRange.getBegin().isMacroID() ||
560           Hint->RemoveRange.getEnd().isMacroID()) {
561         BadApples = true;
562         break;
563       }
564     }
565
566     if (!BadApples) {
567       for (const FixItHint *Hint = Hints; Hint != Hints + NumHints; ++Hint) {
568
569         SourceLocation B = Hint->RemoveRange.getBegin();
570         SourceLocation E = Hint->RemoveRange.getEnd();
571
572         std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
573         std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
574
575         // Adjust for token ranges.
576         if (Hint->RemoveRange.isTokenRange())
577           EInfo.second += Lexer::MeasureTokenLength(E, SM, *LangOpts);
578
579         // We specifically do not do word-wrapping or tab-expansion here,
580         // because this is supposed to be easy to parse.
581         PresumedLoc PLoc = SM.getPresumedLoc(B);
582         if (PLoc.isInvalid())
583           break;
584         
585         OS << "fix-it:\"";
586         OS.write_escaped(SM.getPresumedLoc(B).getFilename());
587         OS << "\":{" << SM.getLineNumber(BInfo.first, BInfo.second)
588           << ':' << SM.getColumnNumber(BInfo.first, BInfo.second)
589           << '-' << SM.getLineNumber(EInfo.first, EInfo.second)
590           << ':' << SM.getColumnNumber(EInfo.first, EInfo.second)
591           << "}:\"";
592         OS.write_escaped(Hint->CodeToInsert);
593         OS << "\"\n";
594       }
595     }
596   }
597 }
598
599 /// \brief Skip over whitespace in the string, starting at the given
600 /// index.
601 ///
602 /// \returns The index of the first non-whitespace character that is
603 /// greater than or equal to Idx or, if no such character exists,
604 /// returns the end of the string.
605 static unsigned skipWhitespace(unsigned Idx,
606                                const llvm::SmallVectorImpl<char> &Str,
607                                unsigned Length) {
608   while (Idx < Length && isspace(Str[Idx]))
609     ++Idx;
610   return Idx;
611 }
612
613 /// \brief If the given character is the start of some kind of
614 /// balanced punctuation (e.g., quotes or parentheses), return the
615 /// character that will terminate the punctuation.
616 ///
617 /// \returns The ending punctuation character, if any, or the NULL
618 /// character if the input character does not start any punctuation.
619 static inline char findMatchingPunctuation(char c) {
620   switch (c) {
621   case '\'': return '\'';
622   case '`': return '\'';
623   case '"':  return '"';
624   case '(':  return ')';
625   case '[': return ']';
626   case '{': return '}';
627   default: break;
628   }
629
630   return 0;
631 }
632
633 /// \brief Find the end of the word starting at the given offset
634 /// within a string.
635 ///
636 /// \returns the index pointing one character past the end of the
637 /// word.
638 static unsigned findEndOfWord(unsigned Start,
639                               const llvm::SmallVectorImpl<char> &Str,
640                               unsigned Length, unsigned Column,
641                               unsigned Columns) {
642   assert(Start < Str.size() && "Invalid start position!");
643   unsigned End = Start + 1;
644
645   // If we are already at the end of the string, take that as the word.
646   if (End == Str.size())
647     return End;
648
649   // Determine if the start of the string is actually opening
650   // punctuation, e.g., a quote or parentheses.
651   char EndPunct = findMatchingPunctuation(Str[Start]);
652   if (!EndPunct) {
653     // This is a normal word. Just find the first space character.
654     while (End < Length && !isspace(Str[End]))
655       ++End;
656     return End;
657   }
658
659   // We have the start of a balanced punctuation sequence (quotes,
660   // parentheses, etc.). Determine the full sequence is.
661   llvm::SmallString<16> PunctuationEndStack;
662   PunctuationEndStack.push_back(EndPunct);
663   while (End < Length && !PunctuationEndStack.empty()) {
664     if (Str[End] == PunctuationEndStack.back())
665       PunctuationEndStack.pop_back();
666     else if (char SubEndPunct = findMatchingPunctuation(Str[End]))
667       PunctuationEndStack.push_back(SubEndPunct);
668
669     ++End;
670   }
671
672   // Find the first space character after the punctuation ended.
673   while (End < Length && !isspace(Str[End]))
674     ++End;
675
676   unsigned PunctWordLength = End - Start;
677   if (// If the word fits on this line
678       Column + PunctWordLength <= Columns ||
679       // ... or the word is "short enough" to take up the next line
680       // without too much ugly white space
681       PunctWordLength < Columns/3)
682     return End; // Take the whole thing as a single "word".
683
684   // The whole quoted/parenthesized string is too long to print as a
685   // single "word". Instead, find the "word" that starts just after
686   // the punctuation and use that end-point instead. This will recurse
687   // until it finds something small enough to consider a word.
688   return findEndOfWord(Start + 1, Str, Length, Column + 1, Columns);
689 }
690
691 /// \brief Print the given string to a stream, word-wrapping it to
692 /// some number of columns in the process.
693 ///
694 /// \brief OS the stream to which the word-wrapping string will be
695 /// emitted.
696 ///
697 /// \brief Str the string to word-wrap and output.
698 ///
699 /// \brief Columns the number of columns to word-wrap to.
700 ///
701 /// \brief Column the column number at which the first character of \p
702 /// Str will be printed. This will be non-zero when part of the first
703 /// line has already been printed.
704 ///
705 /// \brief Indentation the number of spaces to indent any lines beyond
706 /// the first line.
707 ///
708 /// \returns true if word-wrapping was required, or false if the
709 /// string fit on the first line.
710 static bool PrintWordWrapped(llvm::raw_ostream &OS,
711                              const llvm::SmallVectorImpl<char> &Str,
712                              unsigned Columns,
713                              unsigned Column = 0,
714                              unsigned Indentation = WordWrapIndentation) {
715   unsigned Length = Str.size();
716
717   // If there is a newline in this message somewhere, find that
718   // newline and split the message into the part before the newline
719   // (which will be word-wrapped) and the part from the newline one
720   // (which will be emitted unchanged).
721   for (unsigned I = 0; I != Length; ++I)
722     if (Str[I] == '\n') {
723       Length = I;
724       break;
725     }
726
727   // The string used to indent each line.
728   llvm::SmallString<16> IndentStr;
729   IndentStr.assign(Indentation, ' ');
730   bool Wrapped = false;
731   for (unsigned WordStart = 0, WordEnd; WordStart < Length;
732        WordStart = WordEnd) {
733     // Find the beginning of the next word.
734     WordStart = skipWhitespace(WordStart, Str, Length);
735     if (WordStart == Length)
736       break;
737
738     // Find the end of this word.
739     WordEnd = findEndOfWord(WordStart, Str, Length, Column, Columns);
740
741     // Does this word fit on the current line?
742     unsigned WordLength = WordEnd - WordStart;
743     if (Column + WordLength < Columns) {
744       // This word fits on the current line; print it there.
745       if (WordStart) {
746         OS << ' ';
747         Column += 1;
748       }
749       OS.write(&Str[WordStart], WordLength);
750       Column += WordLength;
751       continue;
752     }
753
754     // This word does not fit on the current line, so wrap to the next
755     // line.
756     OS << '\n';
757     OS.write(&IndentStr[0], Indentation);
758     OS.write(&Str[WordStart], WordLength);
759     Column = Indentation + WordLength;
760     Wrapped = true;
761   }
762
763   if (Length == Str.size())
764     return Wrapped; // We're done.
765
766   // There is a newline in the message, followed by something that
767   // will not be word-wrapped. Print that.
768   OS.write(&Str[Length], Str.size() - Length);
769   return true;
770 }
771
772 void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
773                                              const DiagnosticInfo &Info) {
774   // Default implementation (Warnings/errors count).
775   DiagnosticClient::HandleDiagnostic(Level, Info);
776
777   // Keeps track of the the starting position of the location
778   // information (e.g., "foo.c:10:4:") that precedes the error
779   // message. We use this information to determine how long the
780   // file+line+column number prefix is.
781   uint64_t StartOfLocationInfo = OS.tell();
782
783   if (!Prefix.empty())
784     OS << Prefix << ": ";
785
786   // If the location is specified, print out a file/line/col and include trace
787   // if enabled.
788   if (Info.getLocation().isValid()) {
789     const SourceManager &SM = Info.getSourceManager();
790     PresumedLoc PLoc = SM.getPresumedLoc(Info.getLocation());
791     if (PLoc.isInvalid()) {
792       // At least print the file name if available:
793       FileID FID = SM.getFileID(Info.getLocation());
794       if (!FID.isInvalid()) {
795         const FileEntry* FE = SM.getFileEntryForID(FID);
796         if (FE && FE->getName()) {
797           OS << FE->getName();
798           if (FE->getDevice() == 0 && FE->getInode() == 0
799               && FE->getFileMode() == 0) {
800             // in PCH is a guess, but a good one:
801             OS << " (in PCH)";
802           }
803           OS << ": ";
804         }
805       }
806     } else {
807       unsigned LineNo = PLoc.getLine();
808
809       // First, if this diagnostic is not in the main file, print out the
810       // "included from" lines.
811       if (LastWarningLoc != PLoc.getIncludeLoc()) {
812         LastWarningLoc = PLoc.getIncludeLoc();
813         PrintIncludeStack(Level, LastWarningLoc, SM);
814         StartOfLocationInfo = OS.tell();
815       }
816
817       // Compute the column number.
818       if (DiagOpts->ShowLocation) {
819         if (DiagOpts->ShowColors)
820           OS.changeColor(savedColor, true);
821
822         OS << PLoc.getFilename();
823         switch (DiagOpts->Format) {
824         case DiagnosticOptions::Clang: OS << ':'  << LineNo; break;
825         case DiagnosticOptions::Msvc:  OS << '('  << LineNo; break;
826         case DiagnosticOptions::Vi:    OS << " +" << LineNo; break;
827         }
828         if (DiagOpts->ShowColumn)
829           if (unsigned ColNo = PLoc.getColumn()) {
830             if (DiagOpts->Format == DiagnosticOptions::Msvc) {
831               OS << ',';
832               ColNo--;
833             } else 
834               OS << ':';
835             OS << ColNo;
836           }
837         switch (DiagOpts->Format) {
838         case DiagnosticOptions::Clang: 
839         case DiagnosticOptions::Vi:    OS << ':';    break;
840         case DiagnosticOptions::Msvc:  OS << ") : "; break;
841         }
842
843                 
844         if (DiagOpts->ShowSourceRanges && Info.getNumRanges()) {
845           FileID CaretFileID =
846             SM.getFileID(SM.getInstantiationLoc(Info.getLocation()));
847           bool PrintedRange = false;
848
849           for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i) {
850             // Ignore invalid ranges.
851             if (!Info.getRange(i).isValid()) continue;
852
853             SourceLocation B = Info.getRange(i).getBegin();
854             SourceLocation E = Info.getRange(i).getEnd();
855             B = SM.getInstantiationLoc(B);
856             E = SM.getInstantiationLoc(E);
857
858             // If the End location and the start location are the same and are a
859             // macro location, then the range was something that came from a
860             // macro expansion or _Pragma.  If this is an object-like macro, the
861             // best we can do is to highlight the range.  If this is a
862             // function-like macro, we'd also like to highlight the arguments.
863             if (B == E && Info.getRange(i).getEnd().isMacroID())
864               E = SM.getInstantiationRange(Info.getRange(i).getEnd()).second;
865
866             std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B);
867             std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E);
868
869             // If the start or end of the range is in another file, just discard
870             // it.
871             if (BInfo.first != CaretFileID || EInfo.first != CaretFileID)
872               continue;
873
874             // Add in the length of the token, so that we cover multi-char
875             // tokens.
876             unsigned TokSize = 0;
877             if (Info.getRange(i).isTokenRange())
878               TokSize = Lexer::MeasureTokenLength(E, SM, *LangOpts);
879
880             OS << '{' << SM.getLineNumber(BInfo.first, BInfo.second) << ':'
881                << SM.getColumnNumber(BInfo.first, BInfo.second) << '-'
882                << SM.getLineNumber(EInfo.first, EInfo.second) << ':'
883                << (SM.getColumnNumber(EInfo.first, EInfo.second)+TokSize)
884                << '}';
885             PrintedRange = true;
886           }
887
888           if (PrintedRange)
889             OS << ':';
890         }
891       }
892       OS << ' ';
893       if (DiagOpts->ShowColors)
894         OS.resetColor();
895     }
896   }
897
898   if (DiagOpts->ShowColors) {
899     // Print diagnostic category in bold and color
900     switch (Level) {
901     case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type");
902     case Diagnostic::Note:    OS.changeColor(noteColor, true); break;
903     case Diagnostic::Warning: OS.changeColor(warningColor, true); break;
904     case Diagnostic::Error:   OS.changeColor(errorColor, true); break;
905     case Diagnostic::Fatal:   OS.changeColor(fatalColor, true); break;
906     }
907   }
908
909   switch (Level) {
910   case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type");
911   case Diagnostic::Note:    OS << "note: "; break;
912   case Diagnostic::Warning: OS << "warning: "; break;
913   case Diagnostic::Error:   OS << "error: "; break;
914   case Diagnostic::Fatal:   OS << "fatal error: "; break;
915   }
916
917   if (DiagOpts->ShowColors)
918     OS.resetColor();
919
920   llvm::SmallString<100> OutStr;
921   Info.FormatDiagnostic(OutStr);
922
923   if (DiagOpts->ShowNames &&
924       !DiagnosticIDs::isBuiltinNote(Info.getID())) {
925     OutStr += " [";
926     OutStr += DiagnosticIDs::getName(Info.getID());
927     OutStr += "]";
928   }
929   
930   std::string OptionName;
931   if (DiagOpts->ShowOptionNames) {
932     // Was this a warning mapped to an error using -Werror or pragma?
933     if (Level == Diagnostic::Error &&
934         DiagnosticIDs::isBuiltinWarningOrExtension(Info.getID())) {
935       diag::Mapping mapping = diag::MAP_IGNORE;
936       Info.getDiags()->getDiagnosticLevel(Info.getID(), Info.getLocation(), 
937                                           &mapping);
938       if (mapping == diag::MAP_WARNING)
939         OptionName += "-Werror";
940     }
941
942     llvm::StringRef Opt = DiagnosticIDs::getWarningOptionForDiag(Info.getID());
943     if (!Opt.empty()) {
944       if (!OptionName.empty())
945         OptionName += ',';
946       OptionName += "-W";
947       OptionName += Opt;
948     } else if (Info.getID() == diag::fatal_too_many_errors) {
949       OptionName = "-ferror-limit=";
950     } else {
951       // If the diagnostic is an extension diagnostic and not enabled by default
952       // then it must have been turned on with -pedantic.
953       bool EnabledByDefault;
954       if (DiagnosticIDs::isBuiltinExtensionDiag(Info.getID(),
955                                                 EnabledByDefault) &&
956           !EnabledByDefault)
957         OptionName = "-pedantic";
958     }
959   }
960   
961   // If the user wants to see category information, include it too.
962   unsigned DiagCategory = 0;
963   if (DiagOpts->ShowCategories)
964     DiagCategory = DiagnosticIDs::getCategoryNumberForDiag(Info.getID());
965
966   // If there is any categorization information, include it.
967   if (!OptionName.empty() || DiagCategory != 0) {
968     bool NeedsComma = false;
969     OutStr += " [";
970     
971     if (!OptionName.empty()) {
972       OutStr += OptionName;
973       NeedsComma = true;
974     }
975     
976     if (DiagCategory) {
977       if (NeedsComma) OutStr += ',';
978       if (DiagOpts->ShowCategories == 1)
979         OutStr += llvm::utostr(DiagCategory);
980       else {
981         assert(DiagOpts->ShowCategories == 2 && "Invalid ShowCategories value");
982         OutStr += DiagnosticIDs::getCategoryNameFromID(DiagCategory);
983       }
984     }
985     
986     OutStr += "]";
987   }
988
989   
990   if (DiagOpts->ShowColors) {
991     // Print warnings, errors and fatal errors in bold, no color
992     switch (Level) {
993     case Diagnostic::Warning: OS.changeColor(savedColor, true); break;
994     case Diagnostic::Error:   OS.changeColor(savedColor, true); break;
995     case Diagnostic::Fatal:   OS.changeColor(savedColor, true); break;
996     default: break; //don't bold notes
997     }
998   }
999
1000   if (DiagOpts->MessageLength) {
1001     // We will be word-wrapping the error message, so compute the
1002     // column number where we currently are (after printing the
1003     // location information).
1004     unsigned Column = OS.tell() - StartOfLocationInfo;
1005     PrintWordWrapped(OS, OutStr, DiagOpts->MessageLength, Column);
1006   } else {
1007     OS.write(OutStr.begin(), OutStr.size());
1008   }
1009   OS << '\n';
1010   if (DiagOpts->ShowColors)
1011     OS.resetColor();
1012
1013   // If caret diagnostics are enabled and we have location, we want to
1014   // emit the caret.  However, we only do this if the location moved
1015   // from the last diagnostic, if the last diagnostic was a note that
1016   // was part of a different warning or error diagnostic, or if the
1017   // diagnostic has ranges.  We don't want to emit the same caret
1018   // multiple times if one loc has multiple diagnostics.
1019   if (DiagOpts->ShowCarets && Info.getLocation().isValid() &&
1020       ((LastLoc != Info.getLocation()) || Info.getNumRanges() ||
1021        (LastCaretDiagnosticWasNote && Level != Diagnostic::Note) ||
1022        Info.getNumFixItHints())) {
1023     // Cache the LastLoc, it allows us to omit duplicate source/caret spewage.
1024     LastLoc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
1025     LastCaretDiagnosticWasNote = (Level == Diagnostic::Note);
1026
1027     // Get the ranges into a local array we can hack on.
1028     CharSourceRange Ranges[20];
1029     unsigned NumRanges = Info.getNumRanges();
1030     assert(NumRanges < 20 && "Out of space");
1031     for (unsigned i = 0; i != NumRanges; ++i)
1032       Ranges[i] = Info.getRange(i);
1033
1034     unsigned NumHints = Info.getNumFixItHints();
1035     for (unsigned i = 0; i != NumHints; ++i) {
1036       const FixItHint &Hint = Info.getFixItHint(i);
1037       if (Hint.RemoveRange.isValid()) {
1038         assert(NumRanges < 20 && "Out of space");
1039         Ranges[NumRanges++] = Hint.RemoveRange;
1040       }
1041     }
1042
1043     unsigned MacroInstSkipStart = 0, MacroInstSkipEnd = 0;
1044     if (DiagOpts && DiagOpts->MacroBacktraceLimit && !LastLoc.isFileID()) {
1045       // Compute the length of the macro-instantiation backtrace, so that we
1046       // can establish which steps in the macro backtrace we'll skip.
1047       SourceLocation Loc = LastLoc;
1048       unsigned Depth = 0;
1049       do {
1050         ++Depth;
1051         Loc = LastLoc.getManager().getImmediateInstantiationRange(Loc).first;
1052       } while (!Loc.isFileID());
1053       
1054       if (Depth > DiagOpts->MacroBacktraceLimit) {
1055         MacroInstSkipStart = DiagOpts->MacroBacktraceLimit / 2 + 
1056                              DiagOpts->MacroBacktraceLimit % 2;
1057         MacroInstSkipEnd = Depth - DiagOpts->MacroBacktraceLimit / 2;
1058       }
1059     }        
1060     
1061     EmitCaretDiagnostic(Level, LastLoc, Ranges, NumRanges, LastLoc.getManager(),
1062                         Info.getFixItHints(),
1063                         Info.getNumFixItHints(),
1064                         DiagOpts->MessageLength, 
1065                         0, MacroInstSkipStart, MacroInstSkipEnd);
1066   }
1067
1068   OS.flush();
1069 }