2016-01-21 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / gcc / diagnostic-show-locus.c
blobe32325486af96e137991a67d19e265424e015b54
1 /* Diagnostic subroutines for printing source-code
2 Copyright (C) 1999-2016 Free Software Foundation, Inc.
3 Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "version.h"
25 #include "demangle.h"
26 #include "intl.h"
27 #include "backtrace.h"
28 #include "diagnostic.h"
29 #include "diagnostic-color.h"
31 #ifdef HAVE_TERMIOS_H
32 # include <termios.h>
33 #endif
35 #ifdef GWINSZ_IN_SYS_IOCTL
36 # include <sys/ioctl.h>
37 #endif
39 /* Classes for rendering source code and diagnostics, within an
40 anonymous namespace.
41 The work is done by "class layout", which embeds and uses
42 "class colorizer" and "class layout_range" to get things done. */
44 namespace {
46 /* The state at a given point of the source code, assuming that we're
47 in a range: which range are we in, and whether we should draw a caret at
48 this point. */
50 struct point_state
52 int range_idx;
53 bool draw_caret_p;
56 /* A class to inject colorization codes when printing the diagnostic locus.
58 It has one kind of colorization for each of:
59 - normal text
60 - range 0 (the "primary location")
61 - range 1
62 - range 2
64 The class caches the lookup of the color codes for the above.
66 The class also has responsibility for tracking which of the above is
67 active, filtering out unnecessary changes. This allows
68 layout::print_source_line and layout::print_annotation_line
69 to simply request a colorization code for *every* character they print,
70 via this class, and have the filtering be done for them here. */
72 class colorizer
74 public:
75 colorizer (diagnostic_context *context,
76 const diagnostic_info *diagnostic);
77 ~colorizer ();
79 void set_range (int range_idx) { set_state (range_idx); }
80 void set_normal_text () { set_state (STATE_NORMAL_TEXT); }
81 void set_fixit_hint () { set_state (0); }
83 private:
84 void set_state (int state);
85 void begin_state (int state);
86 void finish_state (int state);
88 private:
89 static const int STATE_NORMAL_TEXT = -1;
91 diagnostic_context *m_context;
92 const diagnostic_info *m_diagnostic;
93 int m_current_state;
94 const char *m_caret_cs;
95 const char *m_caret_ce;
96 const char *m_range1_cs;
97 const char *m_range2_cs;
98 const char *m_range_ce;
101 /* A point within a layout_range; similar to an expanded_location,
102 but after filtering on file. */
104 class layout_point
106 public:
107 layout_point (const expanded_location &exploc)
108 : m_line (exploc.line),
109 m_column (exploc.column) {}
111 int m_line;
112 int m_column;
115 /* A class for use by "class layout" below: a filtered location_range. */
117 class layout_range
119 public:
120 layout_range (const location_range *loc_range);
122 bool contains_point (int row, int column) const;
124 layout_point m_start;
125 layout_point m_finish;
126 bool m_show_caret_p;
127 layout_point m_caret;
130 /* A struct for use by layout::print_source_line for telling
131 layout::print_annotation_line the extents of the source line that
132 it printed, so that underlines can be clipped appropriately. */
134 struct line_bounds
136 int m_first_non_ws;
137 int m_last_non_ws;
140 /* A class to control the overall layout when printing a diagnostic.
142 The layout is determined within the constructor.
143 It is then printed by repeatedly calling the "print_source_line",
144 "print_annotation_line" and "print_any_fixits" methods.
146 We assume we have disjoint ranges. */
148 class layout
150 public:
151 layout (diagnostic_context *context,
152 const diagnostic_info *diagnostic);
154 int get_first_line () const { return m_first_line; }
155 int get_last_line () const { return m_last_line; }
157 bool print_source_line (int row, line_bounds *lbounds_out);
158 void print_annotation_line (int row, const line_bounds lbounds);
159 void print_any_fixits (int row, const rich_location *richloc);
161 private:
162 bool
163 get_state_at_point (/* Inputs. */
164 int row, int column,
165 int first_non_ws, int last_non_ws,
166 /* Outputs. */
167 point_state *out_state);
170 get_x_bound_for_row (int row, int caret_column,
171 int last_non_ws);
173 void
174 move_to_column (int *column, int dest_column);
176 private:
177 diagnostic_context *m_context;
178 pretty_printer *m_pp;
179 diagnostic_t m_diagnostic_kind;
180 expanded_location m_exploc;
181 colorizer m_colorizer;
182 bool m_colorize_source_p;
183 auto_vec <layout_range> m_layout_ranges;
184 int m_first_line;
185 int m_last_line;
186 int m_x_offset;
189 /* Implementation of "class colorizer". */
191 /* The constructor for "colorizer". Lookup and store color codes for the
192 different kinds of things we might need to print. */
194 colorizer::colorizer (diagnostic_context *context,
195 const diagnostic_info *diagnostic) :
196 m_context (context),
197 m_diagnostic (diagnostic),
198 m_current_state (STATE_NORMAL_TEXT)
200 m_caret_ce = colorize_stop (pp_show_color (context->printer));
201 m_range1_cs = colorize_start (pp_show_color (context->printer), "range1");
202 m_range2_cs = colorize_start (pp_show_color (context->printer), "range2");
203 m_range_ce = colorize_stop (pp_show_color (context->printer));
206 /* The destructor for "colorize". If colorization is on, print a code to
207 turn it off. */
209 colorizer::~colorizer ()
211 finish_state (m_current_state);
214 /* Update state, printing color codes if necessary if there's a state
215 change. */
217 void
218 colorizer::set_state (int new_state)
220 if (m_current_state != new_state)
222 finish_state (m_current_state);
223 m_current_state = new_state;
224 begin_state (new_state);
228 /* Turn on any colorization for STATE. */
230 void
231 colorizer::begin_state (int state)
233 switch (state)
235 case STATE_NORMAL_TEXT:
236 break;
238 case 0:
239 /* Make range 0 be the same color as the "kind" text
240 (error vs warning vs note). */
241 pp_string
242 (m_context->printer,
243 colorize_start (pp_show_color (m_context->printer),
244 diagnostic_get_color_for_kind (m_diagnostic->kind)));
245 break;
247 case 1:
248 pp_string (m_context->printer, m_range1_cs);
249 break;
251 case 2:
252 pp_string (m_context->printer, m_range2_cs);
253 break;
255 default:
256 /* We don't expect more than 3 ranges per diagnostic. */
257 gcc_unreachable ();
258 break;
262 /* Turn off any colorization for STATE. */
264 void
265 colorizer::finish_state (int state)
267 switch (state)
269 case STATE_NORMAL_TEXT:
270 break;
272 case 0:
273 pp_string (m_context->printer, m_caret_ce);
274 break;
276 default:
277 /* Within a range. */
278 gcc_assert (state > 0);
279 pp_string (m_context->printer, m_range_ce);
280 break;
284 /* Implementation of class layout_range. */
286 /* The constructor for class layout_range.
287 Initialize various layout_point fields from expanded_location
288 equivalents; we've already filtered on file. */
290 layout_range::layout_range (const location_range *loc_range)
291 : m_start (loc_range->m_start),
292 m_finish (loc_range->m_finish),
293 m_show_caret_p (loc_range->m_show_caret_p),
294 m_caret (loc_range->m_caret)
298 /* Is (column, row) within the given range?
299 We've already filtered on the file.
301 Ranges are closed (both limits are within the range).
303 Example A: a single-line range:
304 start: (col=22, line=2)
305 finish: (col=38, line=2)
307 |00000011111111112222222222333333333344444444444
308 |34567890123456789012345678901234567890123456789
309 --+-----------------------------------------------
310 01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
311 02|bbbbbbbbbbbbbbbbbbbSwwwwwwwwwwwwwwwFaaaaaaaaaaa
312 03|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
314 Example B: a multiline range with
315 start: (col=14, line=3)
316 finish: (col=08, line=5)
318 |00000011111111112222222222333333333344444444444
319 |34567890123456789012345678901234567890123456789
320 --+-----------------------------------------------
321 01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
322 02|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
323 03|bbbbbbbbbbbSwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
324 04|wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
325 05|wwwwwFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
326 06|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
327 --+-----------------------------------------------
329 Legend:
330 - 'b' indicates a point *before* the range
331 - 'S' indicates the start of the range
332 - 'w' indicates a point within the range
333 - 'F' indicates the finish of the range (which is
334 within it).
335 - 'a' indicates a subsequent point *after* the range. */
337 bool
338 layout_range::contains_point (int row, int column) const
340 gcc_assert (m_start.m_line <= m_finish.m_line);
341 /* ...but the equivalent isn't true for the columns;
342 consider example B in the comment above. */
344 if (row < m_start.m_line)
345 /* Points before the first line of the range are
346 outside it (corresponding to line 01 in example A
347 and lines 01 and 02 in example B above). */
348 return false;
350 if (row == m_start.m_line)
351 /* On same line as start of range (corresponding
352 to line 02 in example A and line 03 in example B). */
354 if (column < m_start.m_column)
355 /* Points on the starting line of the range, but
356 before the column in which it begins. */
357 return false;
359 if (row < m_finish.m_line)
360 /* This is a multiline range; the point
361 is within it (corresponds to line 03 in example B
362 from column 14 onwards) */
363 return true;
364 else
366 /* This is a single-line range. */
367 gcc_assert (row == m_finish.m_line);
368 return column <= m_finish.m_column;
372 /* The point is in a line beyond that containing the
373 start of the range: lines 03 onwards in example A,
374 and lines 04 onwards in example B. */
375 gcc_assert (row > m_start.m_line);
377 if (row > m_finish.m_line)
378 /* The point is beyond the final line of the range
379 (lines 03 onwards in example A, and lines 06 onwards
380 in example B). */
381 return false;
383 if (row < m_finish.m_line)
385 /* The point is in a line that's fully within a multiline
386 range (e.g. line 04 in example B). */
387 gcc_assert (m_start.m_line < m_finish.m_line);
388 return true;
391 gcc_assert (row == m_finish.m_line);
393 return column <= m_finish.m_column;
396 /* Given a source line LINE of length LINE_WIDTH, determine the width
397 without any trailing whitespace. */
399 static int
400 get_line_width_without_trailing_whitespace (const char *line, int line_width)
402 int result = line_width;
403 while (result > 0)
405 char ch = line[result - 1];
406 if (ch == ' ' || ch == '\t')
407 result--;
408 else
409 break;
411 gcc_assert (result >= 0);
412 gcc_assert (result <= line_width);
413 gcc_assert (result == 0 ||
414 (line[result - 1] != ' '
415 && line[result -1] != '\t'));
416 return result;
419 /* Implementation of class layout. */
421 /* Constructor for class layout.
423 Filter the ranges from the rich_location to those that we can
424 sanely print, populating m_layout_ranges.
425 Determine the range of lines that we will print.
426 Determine m_x_offset, to ensure that the primary caret
427 will fit within the max_width provided by the diagnostic_context. */
429 layout::layout (diagnostic_context * context,
430 const diagnostic_info *diagnostic)
431 : m_context (context),
432 m_pp (context->printer),
433 m_diagnostic_kind (diagnostic->kind),
434 m_exploc (diagnostic->richloc->lazily_expand_location ()),
435 m_colorizer (context, diagnostic),
436 m_colorize_source_p (context->colorize_source_p),
437 m_layout_ranges (rich_location::MAX_RANGES),
438 m_first_line (m_exploc.line),
439 m_last_line (m_exploc.line),
440 m_x_offset (0)
442 rich_location *richloc = diagnostic->richloc;
443 for (unsigned int idx = 0; idx < richloc->get_num_locations (); idx++)
445 /* This diagnostic printer can only cope with "sufficiently sane" ranges.
446 Ignore any ranges that are awkward to handle. */
447 const location_range *loc_range = richloc->get_range (idx);
449 /* If any part of the range isn't in the same file as the primary
450 location of this diagnostic, ignore the range. */
451 if (loc_range->m_start.file != m_exploc.file)
452 continue;
453 if (loc_range->m_finish.file != m_exploc.file)
454 continue;
455 if (loc_range->m_show_caret_p)
456 if (loc_range->m_caret.file != m_exploc.file)
457 continue;
459 /* Everything is now known to be in the correct source file,
460 but it may require further sanitization. */
461 layout_range ri (loc_range);
463 /* If we have a range that finishes before it starts (perhaps
464 from something built via macro expansion), printing the
465 range is likely to be nonsensical. Also, attempting to do so
466 breaks assumptions within the printing code (PR c/68473). */
467 if (loc_range->m_start.line > loc_range->m_finish.line)
469 /* Is this the primary location? */
470 if (m_layout_ranges.length () == 0)
472 /* We want to print the caret for the primary location, but
473 we must sanitize away m_start and m_finish. */
474 ri.m_start = ri.m_caret;
475 ri.m_finish = ri.m_caret;
477 else
478 /* This is a non-primary range; ignore it. */
479 continue;
482 /* Passed all the tests; add the range to m_layout_ranges so that
483 it will be printed. */
484 m_layout_ranges.safe_push (ri);
486 /* Update m_first_line/m_last_line if necessary. */
487 if (ri.m_start.m_line < m_first_line)
488 m_first_line = ri.m_start.m_line;
489 if (ri.m_finish.m_line > m_last_line)
490 m_last_line = ri.m_finish.m_line;
493 /* Adjust m_x_offset.
494 Center the primary caret to fit in max_width; all columns
495 will be adjusted accordingly. */
496 int max_width = m_context->caret_max_width;
497 int line_width;
498 const char *line = location_get_source_line (m_exploc.file, m_exploc.line,
499 &line_width);
500 if (line && m_exploc.column <= line_width)
502 int right_margin = CARET_LINE_MARGIN;
503 int column = m_exploc.column;
504 right_margin = MIN (line_width - column, right_margin);
505 right_margin = max_width - right_margin;
506 if (line_width >= max_width && column > right_margin)
507 m_x_offset = column - right_margin;
508 gcc_assert (m_x_offset >= 0);
512 /* Attempt to print line ROW of source code, potentially colorized at any
513 ranges.
514 Return true if the line was printed, populating *LBOUNDS_OUT.
515 Return false if the source line could not be read, leaving *LBOUNDS_OUT
516 untouched. */
518 bool
519 layout::print_source_line (int row, line_bounds *lbounds_out)
521 int line_width;
522 const char *line = location_get_source_line (m_exploc.file, row,
523 &line_width);
524 if (!line)
525 return false;
527 m_colorizer.set_normal_text ();
529 /* We will stop printing the source line at any trailing
530 whitespace. */
531 line_width = get_line_width_without_trailing_whitespace (line,
532 line_width);
533 line += m_x_offset;
535 pp_space (m_pp);
536 int first_non_ws = INT_MAX;
537 int last_non_ws = 0;
538 int column;
539 for (column = 1 + m_x_offset; column <= line_width; column++)
541 /* Assuming colorization is enabled for the caret and underline
542 characters, we may also colorize the associated characters
543 within the source line.
545 For frontends that generate range information, we color the
546 associated characters in the source line the same as the
547 carets and underlines in the annotation line, to make it easier
548 for the reader to see the pertinent code.
550 For frontends that only generate carets, we don't colorize the
551 characters above them, since this would look strange (e.g.
552 colorizing just the first character in a token). */
553 if (m_colorize_source_p)
555 bool in_range_p;
556 point_state state;
557 in_range_p = get_state_at_point (row, column,
558 0, INT_MAX,
559 &state);
560 if (in_range_p)
561 m_colorizer.set_range (state.range_idx);
562 else
563 m_colorizer.set_normal_text ();
565 char c = *line == '\t' ? ' ' : *line;
566 if (c == '\0')
567 c = ' ';
568 if (c != ' ')
570 last_non_ws = column;
571 if (first_non_ws == INT_MAX)
572 first_non_ws = column;
574 pp_character (m_pp, c);
575 line++;
577 pp_newline (m_pp);
579 lbounds_out->m_first_non_ws = first_non_ws;
580 lbounds_out->m_last_non_ws = last_non_ws;
581 return true;
584 /* Print a line consisting of the caret/underlines for the given
585 source line. */
587 void
588 layout::print_annotation_line (int row, const line_bounds lbounds)
590 int x_bound = get_x_bound_for_row (row, m_exploc.column,
591 lbounds.m_last_non_ws);
593 pp_space (m_pp);
594 for (int column = 1 + m_x_offset; column < x_bound; column++)
596 bool in_range_p;
597 point_state state;
598 in_range_p = get_state_at_point (row, column,
599 lbounds.m_first_non_ws,
600 lbounds.m_last_non_ws,
601 &state);
602 if (in_range_p)
604 /* Within a range. Draw either the caret or an underline. */
605 m_colorizer.set_range (state.range_idx);
606 if (state.draw_caret_p)
607 /* Draw the caret. */
608 pp_character (m_pp, m_context->caret_chars[state.range_idx]);
609 else
610 pp_character (m_pp, '~');
612 else
614 /* Not in a range. */
615 m_colorizer.set_normal_text ();
616 pp_character (m_pp, ' ');
619 pp_newline (m_pp);
622 /* If there are any fixit hints on source line ROW within RICHLOC, print them.
623 They are printed in order, attempting to combine them onto lines, but
624 starting new lines if necessary. */
626 void
627 layout::print_any_fixits (int row, const rich_location *richloc)
629 int column = 0;
630 for (unsigned int i = 0; i < richloc->get_num_fixit_hints (); i++)
632 fixit_hint *hint = richloc->get_fixit_hint (i);
633 if (hint->affects_line_p (m_exploc.file, row))
635 /* For now we assume each fixit hint can only touch one line. */
636 switch (hint->get_kind ())
638 case fixit_hint::INSERT:
640 fixit_insert *insert = static_cast <fixit_insert *> (hint);
641 /* This assumes the insertion just affects one line. */
642 int start_column
643 = LOCATION_COLUMN (insert->get_location ());
644 move_to_column (&column, start_column);
645 m_colorizer.set_fixit_hint ();
646 pp_string (m_pp, insert->get_string ());
647 m_colorizer.set_normal_text ();
648 column += insert->get_length ();
650 break;
652 case fixit_hint::REMOVE:
654 fixit_remove *remove = static_cast <fixit_remove *> (hint);
655 /* This assumes the removal just affects one line. */
656 source_range src_range = remove->get_range ();
657 int start_column = LOCATION_COLUMN (src_range.m_start);
658 int finish_column = LOCATION_COLUMN (src_range.m_finish);
659 move_to_column (&column, start_column);
660 for (int column = start_column; column <= finish_column; column++)
662 m_colorizer.set_fixit_hint ();
663 pp_character (m_pp, '-');
664 m_colorizer.set_normal_text ();
667 break;
669 case fixit_hint::REPLACE:
671 fixit_replace *replace = static_cast <fixit_replace *> (hint);
672 int start_column
673 = LOCATION_COLUMN (replace->get_range ().m_start);
674 move_to_column (&column, start_column);
675 m_colorizer.set_fixit_hint ();
676 pp_string (m_pp, replace->get_string ());
677 m_colorizer.set_normal_text ();
678 column += replace->get_length ();
680 break;
682 default:
683 gcc_unreachable ();
689 /* Return true if (ROW/COLUMN) is within a range of the layout.
690 If it returns true, OUT_STATE is written to, with the
691 range index, and whether we should draw the caret at
692 (ROW/COLUMN) (as opposed to an underline). */
694 bool
695 layout::get_state_at_point (/* Inputs. */
696 int row, int column,
697 int first_non_ws, int last_non_ws,
698 /* Outputs. */
699 point_state *out_state)
701 layout_range *range;
702 int i;
703 FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
705 if (range->contains_point (row, column))
707 out_state->range_idx = i;
709 /* Are we at the range's caret? is it visible? */
710 out_state->draw_caret_p = false;
711 if (row == range->m_caret.m_line
712 && column == range->m_caret.m_column)
713 out_state->draw_caret_p = range->m_show_caret_p;
715 /* Within a multiline range, don't display any underline
716 in any leading or trailing whitespace on a line.
717 We do display carets, however. */
718 if (!out_state->draw_caret_p)
719 if (column < first_non_ws || column > last_non_ws)
720 return false;
722 /* We are within a range. */
723 return true;
727 return false;
730 /* Helper function for use by layout::print_line when printing the
731 annotation line under the source line.
732 Get the column beyond the rightmost one that could contain a caret or
733 range marker, given that we stop rendering at trailing whitespace.
734 ROW is the source line within the given file.
735 CARET_COLUMN is the column of range 0's caret.
736 LAST_NON_WS_COLUMN is the last column containing a non-whitespace
737 character of source (as determined when printing the source line). */
740 layout::get_x_bound_for_row (int row, int caret_column,
741 int last_non_ws_column)
743 int result = caret_column + 1;
745 layout_range *range;
746 int i;
747 FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
749 if (row >= range->m_start.m_line)
751 if (range->m_finish.m_line == row)
753 /* On the final line within a range; ensure that
754 we render up to the end of the range. */
755 if (result <= range->m_finish.m_column)
756 result = range->m_finish.m_column + 1;
758 else if (row < range->m_finish.m_line)
760 /* Within a multiline range; ensure that we render up to the
761 last non-whitespace column. */
762 if (result <= last_non_ws_column)
763 result = last_non_ws_column + 1;
768 return result;
771 /* Given *COLUMN as an x-coordinate, print spaces to position
772 successive output at DEST_COLUMN, printing a newline if necessary,
773 and updating *COLUMN. */
775 void
776 layout::move_to_column (int *column, int dest_column)
778 /* Start a new line if we need to. */
779 if (*column > dest_column)
781 pp_newline (m_pp);
782 *column = 0;
785 while (*column < dest_column)
787 pp_space (m_pp);
788 (*column)++;
792 } /* End of anonymous namespace. */
794 /* Print the physical source code corresponding to the location of
795 this diagnostic, with additional annotations. */
797 void
798 diagnostic_show_locus (diagnostic_context * context,
799 const diagnostic_info *diagnostic)
801 if (!context->show_caret
802 || diagnostic_location (diagnostic, 0) <= BUILTINS_LOCATION
803 || diagnostic_location (diagnostic, 0) == context->last_location)
804 return;
806 context->last_location = diagnostic_location (diagnostic, 0);
808 pp_newline (context->printer);
810 const char *saved_prefix = pp_get_prefix (context->printer);
811 pp_set_prefix (context->printer, NULL);
814 layout layout (context, diagnostic);
815 int last_line = layout.get_last_line ();
816 for (int row = layout.get_first_line ();
817 row <= last_line;
818 row++)
820 /* Print the source line, followed by an annotation line
821 consisting of any caret/underlines, then any fixits.
822 If the source line can't be read, print nothing. */
823 line_bounds lbounds;
824 if (layout.print_source_line (row, &lbounds))
826 layout.print_annotation_line (row, lbounds);
827 layout.print_any_fixits (row, diagnostic->richloc);
831 /* The closing scope here leads to the dtor for layout and thus
832 colorizer being called here, which affects the precise
833 place where colorization is turned off in the unittest
834 for colorized output. */
837 pp_set_prefix (context->printer, saved_prefix);