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
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
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/>. */
23 #include "coretypes.h"
27 #include "backtrace.h"
28 #include "diagnostic.h"
29 #include "diagnostic-color.h"
35 #ifdef GWINSZ_IN_SYS_IOCTL
36 # include <sys/ioctl.h>
39 /* Classes for rendering source code and diagnostics, within an
41 The work is done by "class layout", which embeds and uses
42 "class colorizer" and "class layout_range" to get things done. */
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
56 /* A class to inject colorization codes when printing the diagnostic locus.
58 It has one kind of colorization for each of:
60 - range 0 (the "primary location")
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. */
75 colorizer (diagnostic_context
*context
,
76 const diagnostic_info
*diagnostic
);
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); }
84 void set_state (int state
);
85 void begin_state (int state
);
86 void finish_state (int state
);
89 static const int STATE_NORMAL_TEXT
= -1;
91 diagnostic_context
*m_context
;
92 const diagnostic_info
*m_diagnostic
;
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. */
107 layout_point (const expanded_location
&exploc
)
108 : m_line (exploc
.line
),
109 m_column (exploc
.column
) {}
115 /* A class for use by "class layout" below: a filtered location_range. */
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
;
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. */
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. */
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
);
162 void print_newline ();
165 get_state_at_point (/* Inputs. */
167 int first_non_ws
, int last_non_ws
,
169 point_state
*out_state
);
172 get_x_bound_for_row (int row
, int caret_column
,
176 move_to_column (int *column
, int dest_column
);
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
;
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
) :
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
211 colorizer::~colorizer ()
213 finish_state (m_current_state
);
216 /* Update state, printing color codes if necessary if there's a state
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. */
233 colorizer::begin_state (int state
)
237 case STATE_NORMAL_TEXT
:
241 /* Make range 0 be the same color as the "kind" text
242 (error vs warning vs note). */
245 colorize_start (pp_show_color (m_context
->printer
),
246 diagnostic_get_color_for_kind (m_diagnostic
->kind
)));
250 pp_string (m_context
->printer
, m_range1_cs
);
254 pp_string (m_context
->printer
, m_range2_cs
);
258 /* We don't expect more than 3 ranges per diagnostic. */
264 /* Turn off any colorization for STATE. */
267 colorizer::finish_state (int state
)
271 case STATE_NORMAL_TEXT
:
275 pp_string (m_context
->printer
, m_caret_ce
);
279 /* Within a range. */
280 gcc_assert (state
> 0);
281 pp_string (m_context
->printer
, m_range_ce
);
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 --+-----------------------------------------------
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
337 - 'a' indicates a subsequent point *after* the range. */
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). */
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. */
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) */
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
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
);
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. */
402 get_line_width_without_trailing_whitespace (const char *line
, int line_width
)
404 int result
= line_width
;
407 char ch
= line
[result
- 1];
408 if (ch
== ' ' || ch
== '\t')
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'));
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
),
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
)
455 if (loc_range
->m_finish
.file
!= m_exploc
.file
)
457 if (loc_range
->m_show_caret_p
)
458 if (loc_range
->m_caret
.file
!= m_exploc
.file
)
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
;
480 /* This is a non-primary range; ignore it. */
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
;
500 const char *line
= location_get_source_line (m_exploc
.file
, m_exploc
.line
,
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
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
521 layout::print_source_line (int row
, line_bounds
*lbounds_out
)
524 const char *line
= location_get_source_line (m_exploc
.file
, row
,
529 m_colorizer
.set_normal_text ();
531 /* We will stop printing the source line at any trailing
533 line_width
= get_line_width_without_trailing_whitespace (line
,
538 int first_non_ws
= INT_MAX
;
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
)
559 in_range_p
= get_state_at_point (row
, column
,
563 m_colorizer
.set_range (state
.range_idx
);
565 m_colorizer
.set_normal_text ();
567 char c
= *line
== '\t' ? ' ' : *line
;
572 last_non_ws
= column
;
573 if (first_non_ws
== INT_MAX
)
574 first_non_ws
= column
;
576 pp_character (m_pp
, c
);
581 lbounds_out
->m_first_non_ws
= first_non_ws
;
582 lbounds_out
->m_last_non_ws
= last_non_ws
;
586 /* Print a line consisting of the caret/underlines for the given
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
);
596 for (int column
= 1 + m_x_offset
; column
< x_bound
; column
++)
600 in_range_p
= get_state_at_point (row
, column
,
601 lbounds
.m_first_non_ws
,
602 lbounds
.m_last_non_ws
,
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
]);
612 pp_character (m_pp
, '~');
616 /* Not in a range. */
617 m_colorizer
.set_normal_text ();
618 pp_character (m_pp
, ' ');
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. */
629 layout::print_any_fixits (int row
, const rich_location
*richloc
)
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. */
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 ();
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 ();
671 case fixit_hint::REPLACE
:
673 fixit_replace
*replace
= static_cast <fixit_replace
*> (hint
);
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 ();
690 /* Add a trailing newline, if necessary. */
691 move_to_column (&column
, 0);
694 /* Disable any colorization and emit a newline. */
697 layout::print_newline ()
699 m_colorizer
.set_normal_text ();
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). */
709 layout::get_state_at_point (/* Inputs. */
711 int first_non_ws
, int last_non_ws
,
713 point_state
*out_state
)
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
)
736 /* We are within a range. */
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;
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;
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. */
790 layout::move_to_column (int *column
, int dest_column
)
792 /* Start a new line if we need to. */
793 if (*column
> dest_column
)
799 while (*column
< dest_column
)
806 } /* End of anonymous namespace. */
808 /* Print the physical source code corresponding to the location of
809 this diagnostic, with additional annotations. */
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
)
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. */
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
);