Add qdf24xx base tuning support.
[official-gcc.git] / gcc / diagnostic-show-locus.c
blob7aab658b697c73977e1d7ac5895ea8528da6e6bc
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"
30 #include "selftest.h"
32 #ifdef HAVE_TERMIOS_H
33 # include <termios.h>
34 #endif
36 #ifdef GWINSZ_IN_SYS_IOCTL
37 # include <sys/ioctl.h>
38 #endif
40 /* Classes for rendering source code and diagnostics, within an
41 anonymous namespace.
42 The work is done by "class layout", which embeds and uses
43 "class colorizer" and "class layout_range" to get things done. */
45 namespace {
47 /* The state at a given point of the source code, assuming that we're
48 in a range: which range are we in, and whether we should draw a caret at
49 this point. */
51 struct point_state
53 int range_idx;
54 bool draw_caret_p;
57 /* A class to inject colorization codes when printing the diagnostic locus.
59 It has one kind of colorization for each of:
60 - normal text
61 - range 0 (the "primary location")
62 - range 1
63 - range 2
65 The class caches the lookup of the color codes for the above.
67 The class also has responsibility for tracking which of the above is
68 active, filtering out unnecessary changes. This allows
69 layout::print_source_line and layout::print_annotation_line
70 to simply request a colorization code for *every* character they print,
71 via this class, and have the filtering be done for them here. */
73 class colorizer
75 public:
76 colorizer (diagnostic_context *context,
77 const diagnostic_info *diagnostic);
78 ~colorizer ();
80 void set_range (int range_idx) { set_state (range_idx); }
81 void set_normal_text () { set_state (STATE_NORMAL_TEXT); }
82 void set_fixit_hint () { set_state (0); }
84 private:
85 void set_state (int state);
86 void begin_state (int state);
87 void finish_state (int state);
89 private:
90 static const int STATE_NORMAL_TEXT = -1;
92 diagnostic_context *m_context;
93 const diagnostic_info *m_diagnostic;
94 int m_current_state;
95 const char *m_caret_cs;
96 const char *m_caret_ce;
97 const char *m_range1_cs;
98 const char *m_range2_cs;
99 const char *m_range_ce;
102 /* A point within a layout_range; similar to an expanded_location,
103 but after filtering on file. */
105 class layout_point
107 public:
108 layout_point (const expanded_location &exploc)
109 : m_line (exploc.line),
110 m_column (exploc.column) {}
112 int m_line;
113 int m_column;
116 /* A class for use by "class layout" below: a filtered location_range. */
118 class layout_range
120 public:
121 layout_range (const expanded_location *start_exploc,
122 const expanded_location *finish_exploc,
123 bool show_caret_p,
124 const expanded_location *caret_exploc);
126 bool contains_point (int row, int column) const;
128 layout_point m_start;
129 layout_point m_finish;
130 bool m_show_caret_p;
131 layout_point m_caret;
134 /* A struct for use by layout::print_source_line for telling
135 layout::print_annotation_line the extents of the source line that
136 it printed, so that underlines can be clipped appropriately. */
138 struct line_bounds
140 int m_first_non_ws;
141 int m_last_non_ws;
144 /* A range of contiguous source lines within a layout (e.g. "lines 5-10"
145 or "line 23"). During the layout ctor, layout::calculate_line_spans
146 splits the pertinent source lines into a list of disjoint line_span
147 instances (e.g. lines 5-10, lines 15-20, line 23). */
149 struct line_span
151 line_span (linenum_type first_line, linenum_type last_line)
152 : m_first_line (first_line), m_last_line (last_line)
154 gcc_assert (first_line <= last_line);
156 linenum_type get_first_line () const { return m_first_line; }
157 linenum_type get_last_line () const { return m_last_line; }
159 bool contains_line_p (linenum_type line) const
161 return line >= m_first_line && line <= m_last_line;
164 static int comparator (const void *p1, const void *p2)
166 const line_span *ls1 = (const line_span *)p1;
167 const line_span *ls2 = (const line_span *)p2;
168 int first_line_diff = (int)ls1->m_first_line - (int)ls2->m_first_line;
169 if (first_line_diff)
170 return first_line_diff;
171 return (int)ls1->m_last_line - (int)ls2->m_last_line;
174 linenum_type m_first_line;
175 linenum_type m_last_line;
178 /* A class to control the overall layout when printing a diagnostic.
180 The layout is determined within the constructor.
181 It is then printed by repeatedly calling the "print_source_line",
182 "print_annotation_line" and "print_any_fixits" methods.
184 We assume we have disjoint ranges. */
186 class layout
188 public:
189 layout (diagnostic_context *context,
190 const diagnostic_info *diagnostic);
192 int get_num_line_spans () const { return m_line_spans.length (); }
193 const line_span *get_line_span (int idx) const { return &m_line_spans[idx]; }
195 bool print_heading_for_line_span_index_p (int line_span_idx) const;
197 expanded_location get_expanded_location (const line_span *) const;
199 bool print_source_line (int row, line_bounds *lbounds_out);
200 void print_annotation_line (int row, const line_bounds lbounds);
201 void print_any_fixits (int row, const rich_location *richloc);
203 void show_ruler (int max_column) const;
205 private:
206 void calculate_line_spans ();
208 void print_newline ();
210 bool
211 get_state_at_point (/* Inputs. */
212 int row, int column,
213 int first_non_ws, int last_non_ws,
214 /* Outputs. */
215 point_state *out_state);
218 get_x_bound_for_row (int row, int caret_column,
219 int last_non_ws);
221 void
222 move_to_column (int *column, int dest_column);
224 private:
225 diagnostic_context *m_context;
226 pretty_printer *m_pp;
227 diagnostic_t m_diagnostic_kind;
228 expanded_location m_exploc;
229 colorizer m_colorizer;
230 bool m_colorize_source_p;
231 auto_vec <layout_range> m_layout_ranges;
232 auto_vec <line_span> m_line_spans;
233 int m_x_offset;
236 /* Implementation of "class colorizer". */
238 /* The constructor for "colorizer". Lookup and store color codes for the
239 different kinds of things we might need to print. */
241 colorizer::colorizer (diagnostic_context *context,
242 const diagnostic_info *diagnostic) :
243 m_context (context),
244 m_diagnostic (diagnostic),
245 m_current_state (STATE_NORMAL_TEXT)
247 m_caret_ce = colorize_stop (pp_show_color (context->printer));
248 m_range1_cs = colorize_start (pp_show_color (context->printer), "range1");
249 m_range2_cs = colorize_start (pp_show_color (context->printer), "range2");
250 m_range_ce = colorize_stop (pp_show_color (context->printer));
253 /* The destructor for "colorize". If colorization is on, print a code to
254 turn it off. */
256 colorizer::~colorizer ()
258 finish_state (m_current_state);
261 /* Update state, printing color codes if necessary if there's a state
262 change. */
264 void
265 colorizer::set_state (int new_state)
267 if (m_current_state != new_state)
269 finish_state (m_current_state);
270 m_current_state = new_state;
271 begin_state (new_state);
275 /* Turn on any colorization for STATE. */
277 void
278 colorizer::begin_state (int state)
280 switch (state)
282 case STATE_NORMAL_TEXT:
283 break;
285 case 0:
286 /* Make range 0 be the same color as the "kind" text
287 (error vs warning vs note). */
288 pp_string
289 (m_context->printer,
290 colorize_start (pp_show_color (m_context->printer),
291 diagnostic_get_color_for_kind (m_diagnostic->kind)));
292 break;
294 case 1:
295 pp_string (m_context->printer, m_range1_cs);
296 break;
298 case 2:
299 pp_string (m_context->printer, m_range2_cs);
300 break;
302 default:
303 /* We don't expect more than 3 ranges per diagnostic. */
304 gcc_unreachable ();
305 break;
309 /* Turn off any colorization for STATE. */
311 void
312 colorizer::finish_state (int state)
314 switch (state)
316 case STATE_NORMAL_TEXT:
317 break;
319 case 0:
320 pp_string (m_context->printer, m_caret_ce);
321 break;
323 default:
324 /* Within a range. */
325 gcc_assert (state > 0);
326 pp_string (m_context->printer, m_range_ce);
327 break;
331 /* Implementation of class layout_range. */
333 /* The constructor for class layout_range.
334 Initialize various layout_point fields from expanded_location
335 equivalents; we've already filtered on file. */
337 layout_range::layout_range (const expanded_location *start_exploc,
338 const expanded_location *finish_exploc,
339 bool show_caret_p,
340 const expanded_location *caret_exploc)
341 : m_start (*start_exploc),
342 m_finish (*finish_exploc),
343 m_show_caret_p (show_caret_p),
344 m_caret (*caret_exploc)
348 /* Is (column, row) within the given range?
349 We've already filtered on the file.
351 Ranges are closed (both limits are within the range).
353 Example A: a single-line range:
354 start: (col=22, line=2)
355 finish: (col=38, line=2)
357 |00000011111111112222222222333333333344444444444
358 |34567890123456789012345678901234567890123456789
359 --+-----------------------------------------------
360 01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
361 02|bbbbbbbbbbbbbbbbbbbSwwwwwwwwwwwwwwwFaaaaaaaaaaa
362 03|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
364 Example B: a multiline range with
365 start: (col=14, line=3)
366 finish: (col=08, line=5)
368 |00000011111111112222222222333333333344444444444
369 |34567890123456789012345678901234567890123456789
370 --+-----------------------------------------------
371 01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
372 02|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
373 03|bbbbbbbbbbbSwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
374 04|wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
375 05|wwwwwFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
376 06|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
377 --+-----------------------------------------------
379 Legend:
380 - 'b' indicates a point *before* the range
381 - 'S' indicates the start of the range
382 - 'w' indicates a point within the range
383 - 'F' indicates the finish of the range (which is
384 within it).
385 - 'a' indicates a subsequent point *after* the range. */
387 bool
388 layout_range::contains_point (int row, int column) const
390 gcc_assert (m_start.m_line <= m_finish.m_line);
391 /* ...but the equivalent isn't true for the columns;
392 consider example B in the comment above. */
394 if (row < m_start.m_line)
395 /* Points before the first line of the range are
396 outside it (corresponding to line 01 in example A
397 and lines 01 and 02 in example B above). */
398 return false;
400 if (row == m_start.m_line)
401 /* On same line as start of range (corresponding
402 to line 02 in example A and line 03 in example B). */
404 if (column < m_start.m_column)
405 /* Points on the starting line of the range, but
406 before the column in which it begins. */
407 return false;
409 if (row < m_finish.m_line)
410 /* This is a multiline range; the point
411 is within it (corresponds to line 03 in example B
412 from column 14 onwards) */
413 return true;
414 else
416 /* This is a single-line range. */
417 gcc_assert (row == m_finish.m_line);
418 return column <= m_finish.m_column;
422 /* The point is in a line beyond that containing the
423 start of the range: lines 03 onwards in example A,
424 and lines 04 onwards in example B. */
425 gcc_assert (row > m_start.m_line);
427 if (row > m_finish.m_line)
428 /* The point is beyond the final line of the range
429 (lines 03 onwards in example A, and lines 06 onwards
430 in example B). */
431 return false;
433 if (row < m_finish.m_line)
435 /* The point is in a line that's fully within a multiline
436 range (e.g. line 04 in example B). */
437 gcc_assert (m_start.m_line < m_finish.m_line);
438 return true;
441 gcc_assert (row == m_finish.m_line);
443 return column <= m_finish.m_column;
446 #if CHECKING_P
448 /* A helper function for testing layout_range::contains_point. */
450 static layout_range
451 make_range (int start_line, int start_col, int end_line, int end_col)
453 const expanded_location start_exploc
454 = {"test.c", start_line, start_col, NULL, false};
455 const expanded_location finish_exploc
456 = {"test.c", end_line, end_col, NULL, false};
457 return layout_range (&start_exploc, &finish_exploc, false,
458 &start_exploc);
461 /* Selftests for layout_range::contains_point. */
463 /* Selftest for layout_range::contains_point where the layout_range
464 is a range with start==end i.e. a single point. */
466 static void
467 test_range_contains_point_for_single_point ()
469 layout_range point = make_range (7, 10, 7, 10);
471 /* Before the line. */
472 ASSERT_FALSE (point.contains_point (6, 1));
474 /* On the line, but before start. */
475 ASSERT_FALSE (point.contains_point (7, 9));
477 /* At the point. */
478 ASSERT_TRUE (point.contains_point (7, 10));
480 /* On the line, after the point. */
481 ASSERT_FALSE (point.contains_point (7, 11));
483 /* After the line. */
484 ASSERT_FALSE (point.contains_point (8, 1));
487 /* Selftest for layout_range::contains_point where the layout_range
488 is the single-line range shown as "Example A" above. */
490 static void
491 test_range_contains_point_for_single_line ()
493 layout_range example_a = make_range (2, 22, 2, 38);
495 /* Before the line. */
496 ASSERT_FALSE (example_a.contains_point (1, 1));
498 /* On the line, but before start. */
499 ASSERT_FALSE (example_a.contains_point (2, 21));
501 /* On the line, at the start. */
502 ASSERT_TRUE (example_a.contains_point (2, 22));
504 /* On the line, within the range. */
505 ASSERT_TRUE (example_a.contains_point (2, 23));
507 /* On the line, at the end. */
508 ASSERT_TRUE (example_a.contains_point (2, 38));
510 /* On the line, after the end. */
511 ASSERT_FALSE (example_a.contains_point (2, 39));
513 /* After the line. */
514 ASSERT_FALSE (example_a.contains_point (2, 39));
517 /* Selftest for layout_range::contains_point where the layout_range
518 is the multi-line range shown as "Example B" above. */
520 static void
521 test_range_contains_point_for_multiple_lines ()
523 layout_range example_b = make_range (3, 14, 5, 8);
525 /* Before first line. */
526 ASSERT_FALSE (example_b.contains_point (1, 1));
528 /* On the first line, but before start. */
529 ASSERT_FALSE (example_b.contains_point (3, 13));
531 /* At the start. */
532 ASSERT_TRUE (example_b.contains_point (3, 14));
534 /* On the first line, within the range. */
535 ASSERT_TRUE (example_b.contains_point (3, 15));
537 /* On an interior line.
538 The column number should not matter; try various boundary
539 values. */
540 ASSERT_TRUE (example_b.contains_point (4, 1));
541 ASSERT_TRUE (example_b.contains_point (4, 7));
542 ASSERT_TRUE (example_b.contains_point (4, 8));
543 ASSERT_TRUE (example_b.contains_point (4, 9));
544 ASSERT_TRUE (example_b.contains_point (4, 13));
545 ASSERT_TRUE (example_b.contains_point (4, 14));
546 ASSERT_TRUE (example_b.contains_point (4, 15));
548 /* On the final line, before the end. */
549 ASSERT_TRUE (example_b.contains_point (5, 7));
551 /* On the final line, at the end. */
552 ASSERT_TRUE (example_b.contains_point (5, 8));
554 /* On the final line, after the end. */
555 ASSERT_FALSE (example_b.contains_point (5, 9));
557 /* After the line. */
558 ASSERT_FALSE (example_b.contains_point (6, 1));
561 #endif /* #if CHECKING_P */
563 /* Given a source line LINE of length LINE_WIDTH, determine the width
564 without any trailing whitespace. */
566 static int
567 get_line_width_without_trailing_whitespace (const char *line, int line_width)
569 int result = line_width;
570 while (result > 0)
572 char ch = line[result - 1];
573 if (ch == ' ' || ch == '\t')
574 result--;
575 else
576 break;
578 gcc_assert (result >= 0);
579 gcc_assert (result <= line_width);
580 gcc_assert (result == 0 ||
581 (line[result - 1] != ' '
582 && line[result -1] != '\t'));
583 return result;
586 #if CHECKING_P
588 /* A helper function for testing get_line_width_without_trailing_whitespace. */
590 static void
591 assert_eq (const char *line, int expected_width)
593 int actual_value
594 = get_line_width_without_trailing_whitespace (line, strlen (line));
595 ASSERT_EQ (actual_value, expected_width);
598 /* Verify that get_line_width_without_trailing_whitespace is sane for
599 various inputs. It is not required to handle newlines. */
601 static void
602 test_get_line_width_without_trailing_whitespace ()
604 assert_eq ("", 0);
605 assert_eq (" ", 0);
606 assert_eq ("\t", 0);
607 assert_eq ("hello world", 11);
608 assert_eq ("hello world ", 11);
609 assert_eq ("hello world \t\t ", 11);
612 #endif /* #if CHECKING_P */
614 /* Helper function for layout's ctor, for sanitizing locations relative
615 to the primary location within a diagnostic.
617 Compare LOC_A and LOC_B to see if it makes sense to print underlines
618 connecting their expanded locations. Doing so is only guaranteed to
619 make sense if the locations share the same macro expansion "history"
620 i.e. they can be traced through the same macro expansions, eventually
621 reaching an ordinary map.
623 This may be too strong a condition, but it effectively sanitizes
624 PR c++/70105, which has an example of printing an expression where the
625 final location of the expression is in a different macro, which
626 erroneously was leading to hundreds of lines of irrelevant source
627 being printed. */
629 static bool
630 compatible_locations_p (location_t loc_a, location_t loc_b)
632 if (IS_ADHOC_LOC (loc_a))
633 loc_a = get_location_from_adhoc_loc (line_table, loc_a);
634 if (IS_ADHOC_LOC (loc_b))
635 loc_b = get_location_from_adhoc_loc (line_table, loc_b);
637 /* If either location is one of the special locations outside of a
638 linemap, they are only compatible if they are equal. */
639 if (loc_a < RESERVED_LOCATION_COUNT
640 || loc_b < RESERVED_LOCATION_COUNT)
641 return loc_a == loc_b;
643 const line_map *map_a = linemap_lookup (line_table, loc_a);
644 linemap_assert (map_a);
646 const line_map *map_b = linemap_lookup (line_table, loc_b);
647 linemap_assert (map_b);
649 /* Are they within the same map? */
650 if (map_a == map_b)
652 /* Are both within the same macro expansion? */
653 if (linemap_macro_expansion_map_p (map_a))
655 /* Expand each location towards the spelling location, and
656 recurse. */
657 const line_map_macro *macro_map = linemap_check_macro (map_a);
658 source_location loc_a_toward_spelling
659 = linemap_macro_map_loc_unwind_toward_spelling (line_table,
660 macro_map,
661 loc_a);
662 source_location loc_b_toward_spelling
663 = linemap_macro_map_loc_unwind_toward_spelling (line_table,
664 macro_map,
665 loc_b);
666 return compatible_locations_p (loc_a_toward_spelling,
667 loc_b_toward_spelling);
670 /* Otherwise they are within the same ordinary map. */
671 return true;
673 else
675 /* Within different maps. */
677 /* If either is within a macro expansion, they are incompatible. */
678 if (linemap_macro_expansion_map_p (map_a)
679 || linemap_macro_expansion_map_p (map_b))
680 return false;
682 /* Within two different ordinary maps; they are compatible iff they
683 are in the same file. */
684 const line_map_ordinary *ord_map_a = linemap_check_ordinary (map_a);
685 const line_map_ordinary *ord_map_b = linemap_check_ordinary (map_b);
686 return ord_map_a->to_file == ord_map_b->to_file;
690 /* Implementation of class layout. */
692 /* Constructor for class layout.
694 Filter the ranges from the rich_location to those that we can
695 sanely print, populating m_layout_ranges.
696 Determine the range of lines that we will print, splitting them
697 up into an ordered list of disjoint spans of contiguous line numbers.
698 Determine m_x_offset, to ensure that the primary caret
699 will fit within the max_width provided by the diagnostic_context. */
701 layout::layout (diagnostic_context * context,
702 const diagnostic_info *diagnostic)
703 : m_context (context),
704 m_pp (context->printer),
705 m_diagnostic_kind (diagnostic->kind),
706 m_exploc (diagnostic->richloc->get_expanded_location (0)),
707 m_colorizer (context, diagnostic),
708 m_colorize_source_p (context->colorize_source_p),
709 m_layout_ranges (rich_location::MAX_RANGES),
710 m_line_spans (1 + rich_location::MAX_RANGES),
711 m_x_offset (0)
713 rich_location *richloc = diagnostic->richloc;
714 source_location primary_loc = richloc->get_range (0)->m_loc;
716 for (unsigned int idx = 0; idx < richloc->get_num_locations (); idx++)
718 /* This diagnostic printer can only cope with "sufficiently sane" ranges.
719 Ignore any ranges that are awkward to handle. */
720 const location_range *loc_range = richloc->get_range (idx);
722 /* Split the "range" into caret and range information. */
723 source_range src_range = get_range_from_loc (line_table, loc_range->m_loc);
725 /* Expand the various locations. */
726 expanded_location start
727 = linemap_client_expand_location_to_spelling_point (src_range.m_start);
728 expanded_location finish
729 = linemap_client_expand_location_to_spelling_point (src_range.m_finish);
730 expanded_location caret
731 = linemap_client_expand_location_to_spelling_point (loc_range->m_loc);
733 /* If any part of the range isn't in the same file as the primary
734 location of this diagnostic, ignore the range. */
735 if (start.file != m_exploc.file)
736 continue;
737 if (finish.file != m_exploc.file)
738 continue;
739 if (loc_range->m_show_caret_p)
740 if (caret.file != m_exploc.file)
741 continue;
743 /* Sanitize the caret location for non-primary ranges. */
744 if (m_layout_ranges.length () > 0)
745 if (loc_range->m_show_caret_p)
746 if (!compatible_locations_p (loc_range->m_loc, primary_loc))
747 /* Discard any non-primary ranges that can't be printed
748 sanely relative to the primary location. */
749 continue;
751 /* Everything is now known to be in the correct source file,
752 but it may require further sanitization. */
753 layout_range ri (&start, &finish, loc_range->m_show_caret_p, &caret);
755 /* If we have a range that finishes before it starts (perhaps
756 from something built via macro expansion), printing the
757 range is likely to be nonsensical. Also, attempting to do so
758 breaks assumptions within the printing code (PR c/68473).
759 Similarly, don't attempt to print ranges if one or both ends
760 of the range aren't sane to print relative to the
761 primary location (PR c++/70105). */
762 if (start.line > finish.line
763 || !compatible_locations_p (src_range.m_start, primary_loc)
764 || !compatible_locations_p (src_range.m_finish, primary_loc))
766 /* Is this the primary location? */
767 if (m_layout_ranges.length () == 0)
769 /* We want to print the caret for the primary location, but
770 we must sanitize away m_start and m_finish. */
771 ri.m_start = ri.m_caret;
772 ri.m_finish = ri.m_caret;
774 else
775 /* This is a non-primary range; ignore it. */
776 continue;
779 /* Passed all the tests; add the range to m_layout_ranges so that
780 it will be printed. */
781 m_layout_ranges.safe_push (ri);
784 /* Populate m_line_spans. */
785 calculate_line_spans ();
787 /* Adjust m_x_offset.
788 Center the primary caret to fit in max_width; all columns
789 will be adjusted accordingly. */
790 int max_width = m_context->caret_max_width;
791 int line_width;
792 const char *line = location_get_source_line (m_exploc.file, m_exploc.line,
793 &line_width);
794 if (line && m_exploc.column <= line_width)
796 int right_margin = CARET_LINE_MARGIN;
797 int column = m_exploc.column;
798 right_margin = MIN (line_width - column, right_margin);
799 right_margin = max_width - right_margin;
800 if (line_width >= max_width && column > right_margin)
801 m_x_offset = column - right_margin;
802 gcc_assert (m_x_offset >= 0);
805 if (context->show_ruler_p)
806 show_ruler (m_x_offset + max_width);
809 /* Return true iff we should print a heading when starting the
810 line span with the given index. */
812 bool
813 layout::print_heading_for_line_span_index_p (int line_span_idx) const
815 /* We print a heading for every change of line span, hence for every
816 line span after the initial one. */
817 if (line_span_idx > 0)
818 return true;
820 /* We also do it for the initial span if the primary location of the
821 diagnostic is in a different span. */
822 if (m_exploc.line > (int)get_line_span (0)->m_last_line)
823 return true;
825 return false;
828 /* Get an expanded_location for the first location of interest within
829 the given line_span.
830 Used when printing a heading to indicate a new line span. */
832 expanded_location
833 layout::get_expanded_location (const line_span *line_span) const
835 /* Whenever possible, use the caret location. */
836 if (line_span->contains_line_p (m_exploc.line))
837 return m_exploc;
839 /* Otherwise, use the start of the first range that's present
840 within the line_span. */
841 for (unsigned int i = 0; i < m_layout_ranges.length (); i++)
843 const layout_range *lr = &m_layout_ranges[i];
844 if (line_span->contains_line_p (lr->m_start.m_line))
846 expanded_location exploc = m_exploc;
847 exploc.line = lr->m_start.m_line;
848 exploc.column = lr->m_start.m_column;
849 return exploc;
853 /* It should not be possible to have a line span that didn't
854 contain any of the layout_range instances. */
855 gcc_unreachable ();
856 return m_exploc;
859 /* We want to print the pertinent source code at a diagnostic. The
860 rich_location can contain multiple locations. This will have been
861 filtered into m_exploc (the caret for the primary location) and
862 m_layout_ranges, for those ranges within the same source file.
864 We will print a subset of the lines within the source file in question,
865 as a collection of "spans" of lines.
867 This function populates m_line_spans with an ordered, disjoint list of
868 the line spans of interest.
870 For example, if the primary caret location is on line 7, with ranges
871 covering lines 5-6 and lines 9-12:
874 005 |RANGE 0
875 006 |RANGE 0
876 007 |PRIMARY CARET
878 009 |RANGE 1
879 010 |RANGE 1
880 011 |RANGE 1
881 012 |RANGE 1
884 then we want two spans: lines 5-7 and lines 9-12. */
886 void
887 layout::calculate_line_spans ()
889 /* This should only be called once, by the ctor. */
890 gcc_assert (m_line_spans.length () == 0);
892 /* Populate tmp_spans with individual spans, for each of
893 m_exploc, and for m_layout_ranges. */
894 auto_vec<line_span> tmp_spans (1 + rich_location::MAX_RANGES);
895 tmp_spans.safe_push (line_span (m_exploc.line, m_exploc.line));
896 for (unsigned int i = 0; i < m_layout_ranges.length (); i++)
898 const layout_range *lr = &m_layout_ranges[i];
899 gcc_assert (lr->m_start.m_line <= lr->m_finish.m_line);
900 tmp_spans.safe_push (line_span (lr->m_start.m_line,
901 lr->m_finish.m_line));
904 /* Sort them. */
905 tmp_spans.qsort(line_span::comparator);
907 /* Now iterate through tmp_spans, copying into m_line_spans, and
908 combining where possible. */
909 gcc_assert (tmp_spans.length () > 0);
910 m_line_spans.safe_push (tmp_spans[0]);
911 for (unsigned int i = 1; i < tmp_spans.length (); i++)
913 line_span *current = &m_line_spans[m_line_spans.length () - 1];
914 const line_span *next = &tmp_spans[i];
915 gcc_assert (next->m_first_line >= current->m_first_line);
916 if (next->m_first_line <= current->m_last_line + 1)
918 /* We can merge them. */
919 if (next->m_last_line > current->m_last_line)
920 current->m_last_line = next->m_last_line;
922 else
924 /* No merger possible. */
925 m_line_spans.safe_push (*next);
929 /* Verify the result, in m_line_spans. */
930 gcc_assert (m_line_spans.length () > 0);
931 for (unsigned int i = 1; i < m_line_spans.length (); i++)
933 const line_span *prev = &m_line_spans[i - 1];
934 const line_span *next = &m_line_spans[i];
935 /* The individual spans must be sane. */
936 gcc_assert (prev->m_first_line <= prev->m_last_line);
937 gcc_assert (next->m_first_line <= next->m_last_line);
938 /* The spans must be ordered. */
939 gcc_assert (prev->m_first_line < next->m_first_line);
940 /* There must be a gap of at least one line between separate spans. */
941 gcc_assert ((prev->m_last_line + 1) < next->m_first_line);
945 /* Attempt to print line ROW of source code, potentially colorized at any
946 ranges.
947 Return true if the line was printed, populating *LBOUNDS_OUT.
948 Return false if the source line could not be read, leaving *LBOUNDS_OUT
949 untouched. */
951 bool
952 layout::print_source_line (int row, line_bounds *lbounds_out)
954 int line_width;
955 const char *line = location_get_source_line (m_exploc.file, row,
956 &line_width);
957 if (!line)
958 return false;
960 m_colorizer.set_normal_text ();
962 /* We will stop printing the source line at any trailing
963 whitespace. */
964 line_width = get_line_width_without_trailing_whitespace (line,
965 line_width);
966 line += m_x_offset;
968 pp_space (m_pp);
969 int first_non_ws = INT_MAX;
970 int last_non_ws = 0;
971 int column;
972 for (column = 1 + m_x_offset; column <= line_width; column++)
974 /* Assuming colorization is enabled for the caret and underline
975 characters, we may also colorize the associated characters
976 within the source line.
978 For frontends that generate range information, we color the
979 associated characters in the source line the same as the
980 carets and underlines in the annotation line, to make it easier
981 for the reader to see the pertinent code.
983 For frontends that only generate carets, we don't colorize the
984 characters above them, since this would look strange (e.g.
985 colorizing just the first character in a token). */
986 if (m_colorize_source_p)
988 bool in_range_p;
989 point_state state;
990 in_range_p = get_state_at_point (row, column,
991 0, INT_MAX,
992 &state);
993 if (in_range_p)
994 m_colorizer.set_range (state.range_idx);
995 else
996 m_colorizer.set_normal_text ();
998 char c = *line == '\t' ? ' ' : *line;
999 if (c == '\0')
1000 c = ' ';
1001 if (c != ' ')
1003 last_non_ws = column;
1004 if (first_non_ws == INT_MAX)
1005 first_non_ws = column;
1007 pp_character (m_pp, c);
1008 line++;
1010 print_newline ();
1012 lbounds_out->m_first_non_ws = first_non_ws;
1013 lbounds_out->m_last_non_ws = last_non_ws;
1014 return true;
1017 /* Print a line consisting of the caret/underlines for the given
1018 source line. */
1020 void
1021 layout::print_annotation_line (int row, const line_bounds lbounds)
1023 int x_bound = get_x_bound_for_row (row, m_exploc.column,
1024 lbounds.m_last_non_ws);
1026 pp_space (m_pp);
1027 for (int column = 1 + m_x_offset; column < x_bound; column++)
1029 bool in_range_p;
1030 point_state state;
1031 in_range_p = get_state_at_point (row, column,
1032 lbounds.m_first_non_ws,
1033 lbounds.m_last_non_ws,
1034 &state);
1035 if (in_range_p)
1037 /* Within a range. Draw either the caret or an underline. */
1038 m_colorizer.set_range (state.range_idx);
1039 if (state.draw_caret_p)
1040 /* Draw the caret. */
1041 pp_character (m_pp, m_context->caret_chars[state.range_idx]);
1042 else
1043 pp_character (m_pp, '~');
1045 else
1047 /* Not in a range. */
1048 m_colorizer.set_normal_text ();
1049 pp_character (m_pp, ' ');
1052 print_newline ();
1055 /* If there are any fixit hints on source line ROW within RICHLOC, print them.
1056 They are printed in order, attempting to combine them onto lines, but
1057 starting new lines if necessary. */
1059 void
1060 layout::print_any_fixits (int row, const rich_location *richloc)
1062 int column = 0;
1063 for (unsigned int i = 0; i < richloc->get_num_fixit_hints (); i++)
1065 fixit_hint *hint = richloc->get_fixit_hint (i);
1066 if (hint->affects_line_p (m_exploc.file, row))
1068 /* For now we assume each fixit hint can only touch one line. */
1069 switch (hint->get_kind ())
1071 case fixit_hint::INSERT:
1073 fixit_insert *insert = static_cast <fixit_insert *> (hint);
1074 /* This assumes the insertion just affects one line. */
1075 int start_column
1076 = LOCATION_COLUMN (insert->get_location ());
1077 move_to_column (&column, start_column);
1078 m_colorizer.set_fixit_hint ();
1079 pp_string (m_pp, insert->get_string ());
1080 m_colorizer.set_normal_text ();
1081 column += insert->get_length ();
1083 break;
1085 case fixit_hint::REMOVE:
1087 fixit_remove *remove = static_cast <fixit_remove *> (hint);
1088 /* This assumes the removal just affects one line. */
1089 source_range src_range = remove->get_range ();
1090 int start_column = LOCATION_COLUMN (src_range.m_start);
1091 int finish_column = LOCATION_COLUMN (src_range.m_finish);
1092 move_to_column (&column, start_column);
1093 for (int column = start_column; column <= finish_column; column++)
1095 m_colorizer.set_fixit_hint ();
1096 pp_character (m_pp, '-');
1097 m_colorizer.set_normal_text ();
1100 break;
1102 case fixit_hint::REPLACE:
1104 fixit_replace *replace = static_cast <fixit_replace *> (hint);
1105 int start_column
1106 = LOCATION_COLUMN (replace->get_range ().m_start);
1107 move_to_column (&column, start_column);
1108 m_colorizer.set_fixit_hint ();
1109 pp_string (m_pp, replace->get_string ());
1110 m_colorizer.set_normal_text ();
1111 column += replace->get_length ();
1113 break;
1115 default:
1116 gcc_unreachable ();
1121 /* Add a trailing newline, if necessary. */
1122 move_to_column (&column, 0);
1125 /* Disable any colorization and emit a newline. */
1127 void
1128 layout::print_newline ()
1130 m_colorizer.set_normal_text ();
1131 pp_newline (m_pp);
1134 /* Return true if (ROW/COLUMN) is within a range of the layout.
1135 If it returns true, OUT_STATE is written to, with the
1136 range index, and whether we should draw the caret at
1137 (ROW/COLUMN) (as opposed to an underline). */
1139 bool
1140 layout::get_state_at_point (/* Inputs. */
1141 int row, int column,
1142 int first_non_ws, int last_non_ws,
1143 /* Outputs. */
1144 point_state *out_state)
1146 layout_range *range;
1147 int i;
1148 FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
1150 if (range->contains_point (row, column))
1152 out_state->range_idx = i;
1154 /* Are we at the range's caret? is it visible? */
1155 out_state->draw_caret_p = false;
1156 if (range->m_show_caret_p
1157 && row == range->m_caret.m_line
1158 && column == range->m_caret.m_column)
1159 out_state->draw_caret_p = true;
1161 /* Within a multiline range, don't display any underline
1162 in any leading or trailing whitespace on a line.
1163 We do display carets, however. */
1164 if (!out_state->draw_caret_p)
1165 if (column < first_non_ws || column > last_non_ws)
1166 return false;
1168 /* We are within a range. */
1169 return true;
1173 return false;
1176 /* Helper function for use by layout::print_line when printing the
1177 annotation line under the source line.
1178 Get the column beyond the rightmost one that could contain a caret or
1179 range marker, given that we stop rendering at trailing whitespace.
1180 ROW is the source line within the given file.
1181 CARET_COLUMN is the column of range 0's caret.
1182 LAST_NON_WS_COLUMN is the last column containing a non-whitespace
1183 character of source (as determined when printing the source line). */
1186 layout::get_x_bound_for_row (int row, int caret_column,
1187 int last_non_ws_column)
1189 int result = caret_column + 1;
1191 layout_range *range;
1192 int i;
1193 FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
1195 if (row >= range->m_start.m_line)
1197 if (range->m_finish.m_line == row)
1199 /* On the final line within a range; ensure that
1200 we render up to the end of the range. */
1201 if (result <= range->m_finish.m_column)
1202 result = range->m_finish.m_column + 1;
1204 else if (row < range->m_finish.m_line)
1206 /* Within a multiline range; ensure that we render up to the
1207 last non-whitespace column. */
1208 if (result <= last_non_ws_column)
1209 result = last_non_ws_column + 1;
1214 return result;
1217 /* Given *COLUMN as an x-coordinate, print spaces to position
1218 successive output at DEST_COLUMN, printing a newline if necessary,
1219 and updating *COLUMN. */
1221 void
1222 layout::move_to_column (int *column, int dest_column)
1224 /* Start a new line if we need to. */
1225 if (*column > dest_column)
1227 print_newline ();
1228 *column = 0;
1231 while (*column < dest_column)
1233 pp_space (m_pp);
1234 (*column)++;
1238 /* For debugging layout issues, render a ruler giving column numbers
1239 (after the 1-column indent). */
1241 void
1242 layout::show_ruler (int max_column) const
1244 /* Hundreds. */
1245 if (max_column > 99)
1247 pp_space (m_pp);
1248 for (int column = 1 + m_x_offset; column <= max_column; column++)
1249 if (0 == column % 10)
1250 pp_character (m_pp, '0' + (column / 100) % 10);
1251 else
1252 pp_space (m_pp);
1253 pp_newline (m_pp);
1256 /* Tens. */
1257 pp_space (m_pp);
1258 for (int column = 1 + m_x_offset; column <= max_column; column++)
1259 if (0 == column % 10)
1260 pp_character (m_pp, '0' + (column / 10) % 10);
1261 else
1262 pp_space (m_pp);
1263 pp_newline (m_pp);
1265 /* Units. */
1266 pp_space (m_pp);
1267 for (int column = 1 + m_x_offset; column <= max_column; column++)
1268 pp_character (m_pp, '0' + (column % 10));
1269 pp_newline (m_pp);
1272 } /* End of anonymous namespace. */
1274 /* Print the physical source code corresponding to the location of
1275 this diagnostic, with additional annotations. */
1277 void
1278 diagnostic_show_locus (diagnostic_context * context,
1279 const diagnostic_info *diagnostic)
1281 pp_newline (context->printer);
1283 if (!context->show_caret
1284 || diagnostic_location (diagnostic, 0) <= BUILTINS_LOCATION
1285 || diagnostic_location (diagnostic, 0) == context->last_location)
1286 return;
1288 context->last_location = diagnostic_location (diagnostic, 0);
1290 const char *saved_prefix = pp_get_prefix (context->printer);
1291 pp_set_prefix (context->printer, NULL);
1293 layout layout (context, diagnostic);
1294 for (int line_span_idx = 0; line_span_idx < layout.get_num_line_spans ();
1295 line_span_idx++)
1297 const line_span *line_span = layout.get_line_span (line_span_idx);
1298 if (layout.print_heading_for_line_span_index_p (line_span_idx))
1300 expanded_location exploc = layout.get_expanded_location (line_span);
1301 context->start_span (context, exploc);
1303 int last_line = line_span->get_last_line ();
1304 for (int row = line_span->get_first_line (); row <= last_line; row++)
1306 /* Print the source line, followed by an annotation line
1307 consisting of any caret/underlines, then any fixits.
1308 If the source line can't be read, print nothing. */
1309 line_bounds lbounds;
1310 if (layout.print_source_line (row, &lbounds))
1312 layout.print_annotation_line (row, lbounds);
1313 layout.print_any_fixits (row, diagnostic->richloc);
1318 pp_set_prefix (context->printer, saved_prefix);
1321 #if CHECKING_P
1323 namespace selftest {
1325 /* Run all of the selftests within this file. */
1327 void
1328 diagnostic_show_locus_c_tests ()
1330 test_range_contains_point_for_single_point ();
1331 test_range_contains_point_for_single_line ();
1332 test_range_contains_point_for_multiple_lines ();
1334 test_get_line_width_without_trailing_whitespace ();
1337 } // namespace selftest
1339 #endif /* #if CHECKING_P */