PR libstdc++/69450
[official-gcc.git] / gcc / diagnostic-show-locus.c
blobd9b6750339b31a0d4c519af4a6a7564b267951e5
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 void print_newline ();
164 bool
165 get_state_at_point (/* Inputs. */
166 int row, int column,
167 int first_non_ws, int last_non_ws,
168 /* Outputs. */
169 point_state *out_state);
172 get_x_bound_for_row (int row, int caret_column,
173 int last_non_ws);
175 void
176 move_to_column (int *column, int dest_column);
178 private:
179 diagnostic_context *m_context;
180 pretty_printer *m_pp;
181 diagnostic_t m_diagnostic_kind;
182 expanded_location m_exploc;
183 colorizer m_colorizer;
184 bool m_colorize_source_p;
185 auto_vec <layout_range> m_layout_ranges;
186 int m_first_line;
187 int m_last_line;
188 int m_x_offset;
191 /* Implementation of "class colorizer". */
193 /* The constructor for "colorizer". Lookup and store color codes for the
194 different kinds of things we might need to print. */
196 colorizer::colorizer (diagnostic_context *context,
197 const diagnostic_info *diagnostic) :
198 m_context (context),
199 m_diagnostic (diagnostic),
200 m_current_state (STATE_NORMAL_TEXT)
202 m_caret_ce = colorize_stop (pp_show_color (context->printer));
203 m_range1_cs = colorize_start (pp_show_color (context->printer), "range1");
204 m_range2_cs = colorize_start (pp_show_color (context->printer), "range2");
205 m_range_ce = colorize_stop (pp_show_color (context->printer));
208 /* The destructor for "colorize". If colorization is on, print a code to
209 turn it off. */
211 colorizer::~colorizer ()
213 finish_state (m_current_state);
216 /* Update state, printing color codes if necessary if there's a state
217 change. */
219 void
220 colorizer::set_state (int new_state)
222 if (m_current_state != new_state)
224 finish_state (m_current_state);
225 m_current_state = new_state;
226 begin_state (new_state);
230 /* Turn on any colorization for STATE. */
232 void
233 colorizer::begin_state (int state)
235 switch (state)
237 case STATE_NORMAL_TEXT:
238 break;
240 case 0:
241 /* Make range 0 be the same color as the "kind" text
242 (error vs warning vs note). */
243 pp_string
244 (m_context->printer,
245 colorize_start (pp_show_color (m_context->printer),
246 diagnostic_get_color_for_kind (m_diagnostic->kind)));
247 break;
249 case 1:
250 pp_string (m_context->printer, m_range1_cs);
251 break;
253 case 2:
254 pp_string (m_context->printer, m_range2_cs);
255 break;
257 default:
258 /* We don't expect more than 3 ranges per diagnostic. */
259 gcc_unreachable ();
260 break;
264 /* Turn off any colorization for STATE. */
266 void
267 colorizer::finish_state (int state)
269 switch (state)
271 case STATE_NORMAL_TEXT:
272 break;
274 case 0:
275 pp_string (m_context->printer, m_caret_ce);
276 break;
278 default:
279 /* Within a range. */
280 gcc_assert (state > 0);
281 pp_string (m_context->printer, m_range_ce);
282 break;
286 /* Implementation of class layout_range. */
288 /* The constructor for class layout_range.
289 Initialize various layout_point fields from expanded_location
290 equivalents; we've already filtered on file. */
292 layout_range::layout_range (const location_range *loc_range)
293 : m_start (loc_range->m_start),
294 m_finish (loc_range->m_finish),
295 m_show_caret_p (loc_range->m_show_caret_p),
296 m_caret (loc_range->m_caret)
300 /* Is (column, row) within the given range?
301 We've already filtered on the file.
303 Ranges are closed (both limits are within the range).
305 Example A: a single-line range:
306 start: (col=22, line=2)
307 finish: (col=38, line=2)
309 |00000011111111112222222222333333333344444444444
310 |34567890123456789012345678901234567890123456789
311 --+-----------------------------------------------
312 01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
313 02|bbbbbbbbbbbbbbbbbbbSwwwwwwwwwwwwwwwFaaaaaaaaaaa
314 03|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
316 Example B: a multiline range with
317 start: (col=14, line=3)
318 finish: (col=08, line=5)
320 |00000011111111112222222222333333333344444444444
321 |34567890123456789012345678901234567890123456789
322 --+-----------------------------------------------
323 01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
324 02|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
325 03|bbbbbbbbbbbSwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
326 04|wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
327 05|wwwwwFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
328 06|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
329 --+-----------------------------------------------
331 Legend:
332 - 'b' indicates a point *before* the range
333 - 'S' indicates the start of the range
334 - 'w' indicates a point within the range
335 - 'F' indicates the finish of the range (which is
336 within it).
337 - 'a' indicates a subsequent point *after* the range. */
339 bool
340 layout_range::contains_point (int row, int column) const
342 gcc_assert (m_start.m_line <= m_finish.m_line);
343 /* ...but the equivalent isn't true for the columns;
344 consider example B in the comment above. */
346 if (row < m_start.m_line)
347 /* Points before the first line of the range are
348 outside it (corresponding to line 01 in example A
349 and lines 01 and 02 in example B above). */
350 return false;
352 if (row == m_start.m_line)
353 /* On same line as start of range (corresponding
354 to line 02 in example A and line 03 in example B). */
356 if (column < m_start.m_column)
357 /* Points on the starting line of the range, but
358 before the column in which it begins. */
359 return false;
361 if (row < m_finish.m_line)
362 /* This is a multiline range; the point
363 is within it (corresponds to line 03 in example B
364 from column 14 onwards) */
365 return true;
366 else
368 /* This is a single-line range. */
369 gcc_assert (row == m_finish.m_line);
370 return column <= m_finish.m_column;
374 /* The point is in a line beyond that containing the
375 start of the range: lines 03 onwards in example A,
376 and lines 04 onwards in example B. */
377 gcc_assert (row > m_start.m_line);
379 if (row > m_finish.m_line)
380 /* The point is beyond the final line of the range
381 (lines 03 onwards in example A, and lines 06 onwards
382 in example B). */
383 return false;
385 if (row < m_finish.m_line)
387 /* The point is in a line that's fully within a multiline
388 range (e.g. line 04 in example B). */
389 gcc_assert (m_start.m_line < m_finish.m_line);
390 return true;
393 gcc_assert (row == m_finish.m_line);
395 return column <= m_finish.m_column;
398 /* Given a source line LINE of length LINE_WIDTH, determine the width
399 without any trailing whitespace. */
401 static int
402 get_line_width_without_trailing_whitespace (const char *line, int line_width)
404 int result = line_width;
405 while (result > 0)
407 char ch = line[result - 1];
408 if (ch == ' ' || ch == '\t')
409 result--;
410 else
411 break;
413 gcc_assert (result >= 0);
414 gcc_assert (result <= line_width);
415 gcc_assert (result == 0 ||
416 (line[result - 1] != ' '
417 && line[result -1] != '\t'));
418 return result;
421 /* Implementation of class layout. */
423 /* Constructor for class layout.
425 Filter the ranges from the rich_location to those that we can
426 sanely print, populating m_layout_ranges.
427 Determine the range of lines that we will print.
428 Determine m_x_offset, to ensure that the primary caret
429 will fit within the max_width provided by the diagnostic_context. */
431 layout::layout (diagnostic_context * context,
432 const diagnostic_info *diagnostic)
433 : m_context (context),
434 m_pp (context->printer),
435 m_diagnostic_kind (diagnostic->kind),
436 m_exploc (diagnostic->richloc->lazily_expand_location ()),
437 m_colorizer (context, diagnostic),
438 m_colorize_source_p (context->colorize_source_p),
439 m_layout_ranges (rich_location::MAX_RANGES),
440 m_first_line (m_exploc.line),
441 m_last_line (m_exploc.line),
442 m_x_offset (0)
444 rich_location *richloc = diagnostic->richloc;
445 for (unsigned int idx = 0; idx < richloc->get_num_locations (); idx++)
447 /* This diagnostic printer can only cope with "sufficiently sane" ranges.
448 Ignore any ranges that are awkward to handle. */
449 const location_range *loc_range = richloc->get_range (idx);
451 /* If any part of the range isn't in the same file as the primary
452 location of this diagnostic, ignore the range. */
453 if (loc_range->m_start.file != m_exploc.file)
454 continue;
455 if (loc_range->m_finish.file != m_exploc.file)
456 continue;
457 if (loc_range->m_show_caret_p)
458 if (loc_range->m_caret.file != m_exploc.file)
459 continue;
461 /* Everything is now known to be in the correct source file,
462 but it may require further sanitization. */
463 layout_range ri (loc_range);
465 /* If we have a range that finishes before it starts (perhaps
466 from something built via macro expansion), printing the
467 range is likely to be nonsensical. Also, attempting to do so
468 breaks assumptions within the printing code (PR c/68473). */
469 if (loc_range->m_start.line > loc_range->m_finish.line)
471 /* Is this the primary location? */
472 if (m_layout_ranges.length () == 0)
474 /* We want to print the caret for the primary location, but
475 we must sanitize away m_start and m_finish. */
476 ri.m_start = ri.m_caret;
477 ri.m_finish = ri.m_caret;
479 else
480 /* This is a non-primary range; ignore it. */
481 continue;
484 /* Passed all the tests; add the range to m_layout_ranges so that
485 it will be printed. */
486 m_layout_ranges.safe_push (ri);
488 /* Update m_first_line/m_last_line if necessary. */
489 if (ri.m_start.m_line < m_first_line)
490 m_first_line = ri.m_start.m_line;
491 if (ri.m_finish.m_line > m_last_line)
492 m_last_line = ri.m_finish.m_line;
495 /* Adjust m_x_offset.
496 Center the primary caret to fit in max_width; all columns
497 will be adjusted accordingly. */
498 int max_width = m_context->caret_max_width;
499 int line_width;
500 const char *line = location_get_source_line (m_exploc.file, m_exploc.line,
501 &line_width);
502 if (line && m_exploc.column <= line_width)
504 int right_margin = CARET_LINE_MARGIN;
505 int column = m_exploc.column;
506 right_margin = MIN (line_width - column, right_margin);
507 right_margin = max_width - right_margin;
508 if (line_width >= max_width && column > right_margin)
509 m_x_offset = column - right_margin;
510 gcc_assert (m_x_offset >= 0);
514 /* Attempt to print line ROW of source code, potentially colorized at any
515 ranges.
516 Return true if the line was printed, populating *LBOUNDS_OUT.
517 Return false if the source line could not be read, leaving *LBOUNDS_OUT
518 untouched. */
520 bool
521 layout::print_source_line (int row, line_bounds *lbounds_out)
523 int line_width;
524 const char *line = location_get_source_line (m_exploc.file, row,
525 &line_width);
526 if (!line)
527 return false;
529 m_colorizer.set_normal_text ();
531 /* We will stop printing the source line at any trailing
532 whitespace. */
533 line_width = get_line_width_without_trailing_whitespace (line,
534 line_width);
535 line += m_x_offset;
537 pp_space (m_pp);
538 int first_non_ws = INT_MAX;
539 int last_non_ws = 0;
540 int column;
541 for (column = 1 + m_x_offset; column <= line_width; column++)
543 /* Assuming colorization is enabled for the caret and underline
544 characters, we may also colorize the associated characters
545 within the source line.
547 For frontends that generate range information, we color the
548 associated characters in the source line the same as the
549 carets and underlines in the annotation line, to make it easier
550 for the reader to see the pertinent code.
552 For frontends that only generate carets, we don't colorize the
553 characters above them, since this would look strange (e.g.
554 colorizing just the first character in a token). */
555 if (m_colorize_source_p)
557 bool in_range_p;
558 point_state state;
559 in_range_p = get_state_at_point (row, column,
560 0, INT_MAX,
561 &state);
562 if (in_range_p)
563 m_colorizer.set_range (state.range_idx);
564 else
565 m_colorizer.set_normal_text ();
567 char c = *line == '\t' ? ' ' : *line;
568 if (c == '\0')
569 c = ' ';
570 if (c != ' ')
572 last_non_ws = column;
573 if (first_non_ws == INT_MAX)
574 first_non_ws = column;
576 pp_character (m_pp, c);
577 line++;
579 print_newline ();
581 lbounds_out->m_first_non_ws = first_non_ws;
582 lbounds_out->m_last_non_ws = last_non_ws;
583 return true;
586 /* Print a line consisting of the caret/underlines for the given
587 source line. */
589 void
590 layout::print_annotation_line (int row, const line_bounds lbounds)
592 int x_bound = get_x_bound_for_row (row, m_exploc.column,
593 lbounds.m_last_non_ws);
595 pp_space (m_pp);
596 for (int column = 1 + m_x_offset; column < x_bound; column++)
598 bool in_range_p;
599 point_state state;
600 in_range_p = get_state_at_point (row, column,
601 lbounds.m_first_non_ws,
602 lbounds.m_last_non_ws,
603 &state);
604 if (in_range_p)
606 /* Within a range. Draw either the caret or an underline. */
607 m_colorizer.set_range (state.range_idx);
608 if (state.draw_caret_p)
609 /* Draw the caret. */
610 pp_character (m_pp, m_context->caret_chars[state.range_idx]);
611 else
612 pp_character (m_pp, '~');
614 else
616 /* Not in a range. */
617 m_colorizer.set_normal_text ();
618 pp_character (m_pp, ' ');
621 print_newline ();
624 /* If there are any fixit hints on source line ROW within RICHLOC, print them.
625 They are printed in order, attempting to combine them onto lines, but
626 starting new lines if necessary. */
628 void
629 layout::print_any_fixits (int row, const rich_location *richloc)
631 int column = 0;
632 for (unsigned int i = 0; i < richloc->get_num_fixit_hints (); i++)
634 fixit_hint *hint = richloc->get_fixit_hint (i);
635 if (hint->affects_line_p (m_exploc.file, row))
637 /* For now we assume each fixit hint can only touch one line. */
638 switch (hint->get_kind ())
640 case fixit_hint::INSERT:
642 fixit_insert *insert = static_cast <fixit_insert *> (hint);
643 /* This assumes the insertion just affects one line. */
644 int start_column
645 = LOCATION_COLUMN (insert->get_location ());
646 move_to_column (&column, start_column);
647 m_colorizer.set_fixit_hint ();
648 pp_string (m_pp, insert->get_string ());
649 m_colorizer.set_normal_text ();
650 column += insert->get_length ();
652 break;
654 case fixit_hint::REMOVE:
656 fixit_remove *remove = static_cast <fixit_remove *> (hint);
657 /* This assumes the removal just affects one line. */
658 source_range src_range = remove->get_range ();
659 int start_column = LOCATION_COLUMN (src_range.m_start);
660 int finish_column = LOCATION_COLUMN (src_range.m_finish);
661 move_to_column (&column, start_column);
662 for (int column = start_column; column <= finish_column; column++)
664 m_colorizer.set_fixit_hint ();
665 pp_character (m_pp, '-');
666 m_colorizer.set_normal_text ();
669 break;
671 case fixit_hint::REPLACE:
673 fixit_replace *replace = static_cast <fixit_replace *> (hint);
674 int start_column
675 = LOCATION_COLUMN (replace->get_range ().m_start);
676 move_to_column (&column, start_column);
677 m_colorizer.set_fixit_hint ();
678 pp_string (m_pp, replace->get_string ());
679 m_colorizer.set_normal_text ();
680 column += replace->get_length ();
682 break;
684 default:
685 gcc_unreachable ();
690 /* Add a trailing newline, if necessary. */
691 move_to_column (&column, 0);
694 /* Disable any colorization and emit a newline. */
696 void
697 layout::print_newline ()
699 m_colorizer.set_normal_text ();
700 pp_newline (m_pp);
703 /* Return true if (ROW/COLUMN) is within a range of the layout.
704 If it returns true, OUT_STATE is written to, with the
705 range index, and whether we should draw the caret at
706 (ROW/COLUMN) (as opposed to an underline). */
708 bool
709 layout::get_state_at_point (/* Inputs. */
710 int row, int column,
711 int first_non_ws, int last_non_ws,
712 /* Outputs. */
713 point_state *out_state)
715 layout_range *range;
716 int i;
717 FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
719 if (range->contains_point (row, column))
721 out_state->range_idx = i;
723 /* Are we at the range's caret? is it visible? */
724 out_state->draw_caret_p = false;
725 if (row == range->m_caret.m_line
726 && column == range->m_caret.m_column)
727 out_state->draw_caret_p = range->m_show_caret_p;
729 /* Within a multiline range, don't display any underline
730 in any leading or trailing whitespace on a line.
731 We do display carets, however. */
732 if (!out_state->draw_caret_p)
733 if (column < first_non_ws || column > last_non_ws)
734 return false;
736 /* We are within a range. */
737 return true;
741 return false;
744 /* Helper function for use by layout::print_line when printing the
745 annotation line under the source line.
746 Get the column beyond the rightmost one that could contain a caret or
747 range marker, given that we stop rendering at trailing whitespace.
748 ROW is the source line within the given file.
749 CARET_COLUMN is the column of range 0's caret.
750 LAST_NON_WS_COLUMN is the last column containing a non-whitespace
751 character of source (as determined when printing the source line). */
754 layout::get_x_bound_for_row (int row, int caret_column,
755 int last_non_ws_column)
757 int result = caret_column + 1;
759 layout_range *range;
760 int i;
761 FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
763 if (row >= range->m_start.m_line)
765 if (range->m_finish.m_line == row)
767 /* On the final line within a range; ensure that
768 we render up to the end of the range. */
769 if (result <= range->m_finish.m_column)
770 result = range->m_finish.m_column + 1;
772 else if (row < range->m_finish.m_line)
774 /* Within a multiline range; ensure that we render up to the
775 last non-whitespace column. */
776 if (result <= last_non_ws_column)
777 result = last_non_ws_column + 1;
782 return result;
785 /* Given *COLUMN as an x-coordinate, print spaces to position
786 successive output at DEST_COLUMN, printing a newline if necessary,
787 and updating *COLUMN. */
789 void
790 layout::move_to_column (int *column, int dest_column)
792 /* Start a new line if we need to. */
793 if (*column > dest_column)
795 print_newline ();
796 *column = 0;
799 while (*column < dest_column)
801 pp_space (m_pp);
802 (*column)++;
806 } /* End of anonymous namespace. */
808 /* Print the physical source code corresponding to the location of
809 this diagnostic, with additional annotations. */
811 void
812 diagnostic_show_locus (diagnostic_context * context,
813 const diagnostic_info *diagnostic)
815 pp_newline (context->printer);
817 if (!context->show_caret
818 || diagnostic_location (diagnostic, 0) <= BUILTINS_LOCATION
819 || diagnostic_location (diagnostic, 0) == context->last_location)
820 return;
822 context->last_location = diagnostic_location (diagnostic, 0);
824 const char *saved_prefix = pp_get_prefix (context->printer);
825 pp_set_prefix (context->printer, NULL);
827 layout layout (context, diagnostic);
828 int last_line = layout.get_last_line ();
829 for (int row = layout.get_first_line (); row <= last_line; row++)
831 /* Print the source line, followed by an annotation line
832 consisting of any caret/underlines, then any fixits.
833 If the source line can't be read, print nothing. */
834 line_bounds lbounds;
835 if (layout.print_source_line (row, &lbounds))
837 layout.print_annotation_line (row, lbounds);
838 layout.print_any_fixits (row, diagnostic->richloc);
842 pp_set_prefix (context->printer, saved_prefix);