Implement C _FloatN, _FloatNx types.
[official-gcc.git] / gcc / diagnostic-show-locus.c
blob4498f7ce5da3cb35198cc54affa61968efeebd82
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 diagnostic_t diagnostic_kind);
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 diagnostic_t m_diagnostic_kind;
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 rich_location *richloc,
191 diagnostic_t diagnostic_kind);
193 int get_num_line_spans () const { return m_line_spans.length (); }
194 const line_span *get_line_span (int idx) const { return &m_line_spans[idx]; }
196 bool print_heading_for_line_span_index_p (int line_span_idx) const;
198 expanded_location get_expanded_location (const line_span *) const;
200 bool print_source_line (int row, line_bounds *lbounds_out);
201 void print_annotation_line (int row, const line_bounds lbounds);
202 void print_any_fixits (int row, const rich_location *richloc);
204 void show_ruler (int max_column) const;
206 private:
207 void calculate_line_spans ();
209 void print_newline ();
211 bool
212 get_state_at_point (/* Inputs. */
213 int row, int column,
214 int first_non_ws, int last_non_ws,
215 /* Outputs. */
216 point_state *out_state);
219 get_x_bound_for_row (int row, int caret_column,
220 int last_non_ws);
222 void
223 move_to_column (int *column, int dest_column);
225 private:
226 diagnostic_context *m_context;
227 pretty_printer *m_pp;
228 diagnostic_t m_diagnostic_kind;
229 expanded_location m_exploc;
230 colorizer m_colorizer;
231 bool m_colorize_source_p;
232 auto_vec <layout_range> m_layout_ranges;
233 auto_vec <line_span> m_line_spans;
234 int m_x_offset;
237 /* Implementation of "class colorizer". */
239 /* The constructor for "colorizer". Lookup and store color codes for the
240 different kinds of things we might need to print. */
242 colorizer::colorizer (diagnostic_context *context,
243 diagnostic_t diagnostic_kind) :
244 m_context (context),
245 m_diagnostic_kind (diagnostic_kind),
246 m_current_state (STATE_NORMAL_TEXT)
248 m_caret_ce = colorize_stop (pp_show_color (context->printer));
249 m_range1_cs = colorize_start (pp_show_color (context->printer), "range1");
250 m_range2_cs = colorize_start (pp_show_color (context->printer), "range2");
251 m_range_ce = colorize_stop (pp_show_color (context->printer));
254 /* The destructor for "colorize". If colorization is on, print a code to
255 turn it off. */
257 colorizer::~colorizer ()
259 finish_state (m_current_state);
262 /* Update state, printing color codes if necessary if there's a state
263 change. */
265 void
266 colorizer::set_state (int new_state)
268 if (m_current_state != new_state)
270 finish_state (m_current_state);
271 m_current_state = new_state;
272 begin_state (new_state);
276 /* Turn on any colorization for STATE. */
278 void
279 colorizer::begin_state (int state)
281 switch (state)
283 case STATE_NORMAL_TEXT:
284 break;
286 case 0:
287 /* Make range 0 be the same color as the "kind" text
288 (error vs warning vs note). */
289 pp_string
290 (m_context->printer,
291 colorize_start (pp_show_color (m_context->printer),
292 diagnostic_get_color_for_kind (m_diagnostic_kind)));
293 break;
295 case 1:
296 pp_string (m_context->printer, m_range1_cs);
297 break;
299 case 2:
300 pp_string (m_context->printer, m_range2_cs);
301 break;
303 default:
304 /* We don't expect more than 3 ranges per diagnostic. */
305 gcc_unreachable ();
306 break;
310 /* Turn off any colorization for STATE. */
312 void
313 colorizer::finish_state (int state)
315 switch (state)
317 case STATE_NORMAL_TEXT:
318 break;
320 case 0:
321 pp_string (m_context->printer, m_caret_ce);
322 break;
324 default:
325 /* Within a range. */
326 gcc_assert (state > 0);
327 pp_string (m_context->printer, m_range_ce);
328 break;
332 /* Implementation of class layout_range. */
334 /* The constructor for class layout_range.
335 Initialize various layout_point fields from expanded_location
336 equivalents; we've already filtered on file. */
338 layout_range::layout_range (const expanded_location *start_exploc,
339 const expanded_location *finish_exploc,
340 bool show_caret_p,
341 const expanded_location *caret_exploc)
342 : m_start (*start_exploc),
343 m_finish (*finish_exploc),
344 m_show_caret_p (show_caret_p),
345 m_caret (*caret_exploc)
349 /* Is (column, row) within the given range?
350 We've already filtered on the file.
352 Ranges are closed (both limits are within the range).
354 Example A: a single-line range:
355 start: (col=22, line=2)
356 finish: (col=38, line=2)
358 |00000011111111112222222222333333333344444444444
359 |34567890123456789012345678901234567890123456789
360 --+-----------------------------------------------
361 01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
362 02|bbbbbbbbbbbbbbbbbbbSwwwwwwwwwwwwwwwFaaaaaaaaaaa
363 03|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
365 Example B: a multiline range with
366 start: (col=14, line=3)
367 finish: (col=08, line=5)
369 |00000011111111112222222222333333333344444444444
370 |34567890123456789012345678901234567890123456789
371 --+-----------------------------------------------
372 01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
373 02|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
374 03|bbbbbbbbbbbSwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
375 04|wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
376 05|wwwwwFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
377 06|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
378 --+-----------------------------------------------
380 Legend:
381 - 'b' indicates a point *before* the range
382 - 'S' indicates the start of the range
383 - 'w' indicates a point within the range
384 - 'F' indicates the finish of the range (which is
385 within it).
386 - 'a' indicates a subsequent point *after* the range. */
388 bool
389 layout_range::contains_point (int row, int column) const
391 gcc_assert (m_start.m_line <= m_finish.m_line);
392 /* ...but the equivalent isn't true for the columns;
393 consider example B in the comment above. */
395 if (row < m_start.m_line)
396 /* Points before the first line of the range are
397 outside it (corresponding to line 01 in example A
398 and lines 01 and 02 in example B above). */
399 return false;
401 if (row == m_start.m_line)
402 /* On same line as start of range (corresponding
403 to line 02 in example A and line 03 in example B). */
405 if (column < m_start.m_column)
406 /* Points on the starting line of the range, but
407 before the column in which it begins. */
408 return false;
410 if (row < m_finish.m_line)
411 /* This is a multiline range; the point
412 is within it (corresponds to line 03 in example B
413 from column 14 onwards) */
414 return true;
415 else
417 /* This is a single-line range. */
418 gcc_assert (row == m_finish.m_line);
419 return column <= m_finish.m_column;
423 /* The point is in a line beyond that containing the
424 start of the range: lines 03 onwards in example A,
425 and lines 04 onwards in example B. */
426 gcc_assert (row > m_start.m_line);
428 if (row > m_finish.m_line)
429 /* The point is beyond the final line of the range
430 (lines 03 onwards in example A, and lines 06 onwards
431 in example B). */
432 return false;
434 if (row < m_finish.m_line)
436 /* The point is in a line that's fully within a multiline
437 range (e.g. line 04 in example B). */
438 gcc_assert (m_start.m_line < m_finish.m_line);
439 return true;
442 gcc_assert (row == m_finish.m_line);
444 return column <= m_finish.m_column;
447 #if CHECKING_P
449 /* A helper function for testing layout_range::contains_point. */
451 static layout_range
452 make_range (int start_line, int start_col, int end_line, int end_col)
454 const expanded_location start_exploc
455 = {"test.c", start_line, start_col, NULL, false};
456 const expanded_location finish_exploc
457 = {"test.c", end_line, end_col, NULL, false};
458 return layout_range (&start_exploc, &finish_exploc, false,
459 &start_exploc);
462 /* Selftests for layout_range::contains_point. */
464 /* Selftest for layout_range::contains_point where the layout_range
465 is a range with start==end i.e. a single point. */
467 static void
468 test_range_contains_point_for_single_point ()
470 layout_range point = make_range (7, 10, 7, 10);
472 /* Before the line. */
473 ASSERT_FALSE (point.contains_point (6, 1));
475 /* On the line, but before start. */
476 ASSERT_FALSE (point.contains_point (7, 9));
478 /* At the point. */
479 ASSERT_TRUE (point.contains_point (7, 10));
481 /* On the line, after the point. */
482 ASSERT_FALSE (point.contains_point (7, 11));
484 /* After the line. */
485 ASSERT_FALSE (point.contains_point (8, 1));
488 /* Selftest for layout_range::contains_point where the layout_range
489 is the single-line range shown as "Example A" above. */
491 static void
492 test_range_contains_point_for_single_line ()
494 layout_range example_a = make_range (2, 22, 2, 38);
496 /* Before the line. */
497 ASSERT_FALSE (example_a.contains_point (1, 1));
499 /* On the line, but before start. */
500 ASSERT_FALSE (example_a.contains_point (2, 21));
502 /* On the line, at the start. */
503 ASSERT_TRUE (example_a.contains_point (2, 22));
505 /* On the line, within the range. */
506 ASSERT_TRUE (example_a.contains_point (2, 23));
508 /* On the line, at the end. */
509 ASSERT_TRUE (example_a.contains_point (2, 38));
511 /* On the line, after the end. */
512 ASSERT_FALSE (example_a.contains_point (2, 39));
514 /* After the line. */
515 ASSERT_FALSE (example_a.contains_point (2, 39));
518 /* Selftest for layout_range::contains_point where the layout_range
519 is the multi-line range shown as "Example B" above. */
521 static void
522 test_range_contains_point_for_multiple_lines ()
524 layout_range example_b = make_range (3, 14, 5, 8);
526 /* Before first line. */
527 ASSERT_FALSE (example_b.contains_point (1, 1));
529 /* On the first line, but before start. */
530 ASSERT_FALSE (example_b.contains_point (3, 13));
532 /* At the start. */
533 ASSERT_TRUE (example_b.contains_point (3, 14));
535 /* On the first line, within the range. */
536 ASSERT_TRUE (example_b.contains_point (3, 15));
538 /* On an interior line.
539 The column number should not matter; try various boundary
540 values. */
541 ASSERT_TRUE (example_b.contains_point (4, 1));
542 ASSERT_TRUE (example_b.contains_point (4, 7));
543 ASSERT_TRUE (example_b.contains_point (4, 8));
544 ASSERT_TRUE (example_b.contains_point (4, 9));
545 ASSERT_TRUE (example_b.contains_point (4, 13));
546 ASSERT_TRUE (example_b.contains_point (4, 14));
547 ASSERT_TRUE (example_b.contains_point (4, 15));
549 /* On the final line, before the end. */
550 ASSERT_TRUE (example_b.contains_point (5, 7));
552 /* On the final line, at the end. */
553 ASSERT_TRUE (example_b.contains_point (5, 8));
555 /* On the final line, after the end. */
556 ASSERT_FALSE (example_b.contains_point (5, 9));
558 /* After the line. */
559 ASSERT_FALSE (example_b.contains_point (6, 1));
562 #endif /* #if CHECKING_P */
564 /* Given a source line LINE of length LINE_WIDTH, determine the width
565 without any trailing whitespace. */
567 static int
568 get_line_width_without_trailing_whitespace (const char *line, int line_width)
570 int result = line_width;
571 while (result > 0)
573 char ch = line[result - 1];
574 if (ch == ' ' || ch == '\t')
575 result--;
576 else
577 break;
579 gcc_assert (result >= 0);
580 gcc_assert (result <= line_width);
581 gcc_assert (result == 0 ||
582 (line[result - 1] != ' '
583 && line[result -1] != '\t'));
584 return result;
587 #if CHECKING_P
589 /* A helper function for testing get_line_width_without_trailing_whitespace. */
591 static void
592 assert_eq (const char *line, int expected_width)
594 int actual_value
595 = get_line_width_without_trailing_whitespace (line, strlen (line));
596 ASSERT_EQ (actual_value, expected_width);
599 /* Verify that get_line_width_without_trailing_whitespace is sane for
600 various inputs. It is not required to handle newlines. */
602 static void
603 test_get_line_width_without_trailing_whitespace ()
605 assert_eq ("", 0);
606 assert_eq (" ", 0);
607 assert_eq ("\t", 0);
608 assert_eq ("hello world", 11);
609 assert_eq ("hello world ", 11);
610 assert_eq ("hello world \t\t ", 11);
613 #endif /* #if CHECKING_P */
615 /* Helper function for layout's ctor, for sanitizing locations relative
616 to the primary location within a diagnostic.
618 Compare LOC_A and LOC_B to see if it makes sense to print underlines
619 connecting their expanded locations. Doing so is only guaranteed to
620 make sense if the locations share the same macro expansion "history"
621 i.e. they can be traced through the same macro expansions, eventually
622 reaching an ordinary map.
624 This may be too strong a condition, but it effectively sanitizes
625 PR c++/70105, which has an example of printing an expression where the
626 final location of the expression is in a different macro, which
627 erroneously was leading to hundreds of lines of irrelevant source
628 being printed. */
630 static bool
631 compatible_locations_p (location_t loc_a, location_t loc_b)
633 if (IS_ADHOC_LOC (loc_a))
634 loc_a = get_location_from_adhoc_loc (line_table, loc_a);
635 if (IS_ADHOC_LOC (loc_b))
636 loc_b = get_location_from_adhoc_loc (line_table, loc_b);
638 /* If either location is one of the special locations outside of a
639 linemap, they are only compatible if they are equal. */
640 if (loc_a < RESERVED_LOCATION_COUNT
641 || loc_b < RESERVED_LOCATION_COUNT)
642 return loc_a == loc_b;
644 const line_map *map_a = linemap_lookup (line_table, loc_a);
645 linemap_assert (map_a);
647 const line_map *map_b = linemap_lookup (line_table, loc_b);
648 linemap_assert (map_b);
650 /* Are they within the same map? */
651 if (map_a == map_b)
653 /* Are both within the same macro expansion? */
654 if (linemap_macro_expansion_map_p (map_a))
656 /* Expand each location towards the spelling location, and
657 recurse. */
658 const line_map_macro *macro_map = linemap_check_macro (map_a);
659 source_location loc_a_toward_spelling
660 = linemap_macro_map_loc_unwind_toward_spelling (line_table,
661 macro_map,
662 loc_a);
663 source_location loc_b_toward_spelling
664 = linemap_macro_map_loc_unwind_toward_spelling (line_table,
665 macro_map,
666 loc_b);
667 return compatible_locations_p (loc_a_toward_spelling,
668 loc_b_toward_spelling);
671 /* Otherwise they are within the same ordinary map. */
672 return true;
674 else
676 /* Within different maps. */
678 /* If either is within a macro expansion, they are incompatible. */
679 if (linemap_macro_expansion_map_p (map_a)
680 || linemap_macro_expansion_map_p (map_b))
681 return false;
683 /* Within two different ordinary maps; they are compatible iff they
684 are in the same file. */
685 const line_map_ordinary *ord_map_a = linemap_check_ordinary (map_a);
686 const line_map_ordinary *ord_map_b = linemap_check_ordinary (map_b);
687 return ord_map_a->to_file == ord_map_b->to_file;
691 /* Implementation of class layout. */
693 /* Constructor for class layout.
695 Filter the ranges from the rich_location to those that we can
696 sanely print, populating m_layout_ranges.
697 Determine the range of lines that we will print, splitting them
698 up into an ordered list of disjoint spans of contiguous line numbers.
699 Determine m_x_offset, to ensure that the primary caret
700 will fit within the max_width provided by the diagnostic_context. */
702 layout::layout (diagnostic_context * context,
703 rich_location *richloc,
704 diagnostic_t diagnostic_kind)
705 : m_context (context),
706 m_pp (context->printer),
707 m_diagnostic_kind (diagnostic_kind),
708 m_exploc (richloc->get_expanded_location (0)),
709 m_colorizer (context, diagnostic_kind),
710 m_colorize_source_p (context->colorize_source_p),
711 m_layout_ranges (rich_location::MAX_RANGES),
712 m_line_spans (1 + rich_location::MAX_RANGES),
713 m_x_offset (0)
715 source_location primary_loc = richloc->get_range (0)->m_loc;
717 for (unsigned int idx = 0; idx < richloc->get_num_locations (); idx++)
719 /* This diagnostic printer can only cope with "sufficiently sane" ranges.
720 Ignore any ranges that are awkward to handle. */
721 const location_range *loc_range = richloc->get_range (idx);
723 /* Split the "range" into caret and range information. */
724 source_range src_range = get_range_from_loc (line_table, loc_range->m_loc);
726 /* Expand the various locations. */
727 expanded_location start
728 = linemap_client_expand_location_to_spelling_point (src_range.m_start);
729 expanded_location finish
730 = linemap_client_expand_location_to_spelling_point (src_range.m_finish);
731 expanded_location caret
732 = linemap_client_expand_location_to_spelling_point (loc_range->m_loc);
734 /* If any part of the range isn't in the same file as the primary
735 location of this diagnostic, ignore the range. */
736 if (start.file != m_exploc.file)
737 continue;
738 if (finish.file != m_exploc.file)
739 continue;
740 if (loc_range->m_show_caret_p)
741 if (caret.file != m_exploc.file)
742 continue;
744 /* Sanitize the caret location for non-primary ranges. */
745 if (m_layout_ranges.length () > 0)
746 if (loc_range->m_show_caret_p)
747 if (!compatible_locations_p (loc_range->m_loc, primary_loc))
748 /* Discard any non-primary ranges that can't be printed
749 sanely relative to the primary location. */
750 continue;
752 /* Everything is now known to be in the correct source file,
753 but it may require further sanitization. */
754 layout_range ri (&start, &finish, loc_range->m_show_caret_p, &caret);
756 /* If we have a range that finishes before it starts (perhaps
757 from something built via macro expansion), printing the
758 range is likely to be nonsensical. Also, attempting to do so
759 breaks assumptions within the printing code (PR c/68473).
760 Similarly, don't attempt to print ranges if one or both ends
761 of the range aren't sane to print relative to the
762 primary location (PR c++/70105). */
763 if (start.line > finish.line
764 || !compatible_locations_p (src_range.m_start, primary_loc)
765 || !compatible_locations_p (src_range.m_finish, primary_loc))
767 /* Is this the primary location? */
768 if (m_layout_ranges.length () == 0)
770 /* We want to print the caret for the primary location, but
771 we must sanitize away m_start and m_finish. */
772 ri.m_start = ri.m_caret;
773 ri.m_finish = ri.m_caret;
775 else
776 /* This is a non-primary range; ignore it. */
777 continue;
780 /* Passed all the tests; add the range to m_layout_ranges so that
781 it will be printed. */
782 m_layout_ranges.safe_push (ri);
785 /* Populate m_line_spans. */
786 calculate_line_spans ();
788 /* Adjust m_x_offset.
789 Center the primary caret to fit in max_width; all columns
790 will be adjusted accordingly. */
791 int max_width = m_context->caret_max_width;
792 int line_width;
793 const char *line = location_get_source_line (m_exploc.file, m_exploc.line,
794 &line_width);
795 if (line && m_exploc.column <= line_width)
797 int right_margin = CARET_LINE_MARGIN;
798 int column = m_exploc.column;
799 right_margin = MIN (line_width - column, right_margin);
800 right_margin = max_width - right_margin;
801 if (line_width >= max_width && column > right_margin)
802 m_x_offset = column - right_margin;
803 gcc_assert (m_x_offset >= 0);
806 if (context->show_ruler_p)
807 show_ruler (m_x_offset + max_width);
810 /* Return true iff we should print a heading when starting the
811 line span with the given index. */
813 bool
814 layout::print_heading_for_line_span_index_p (int line_span_idx) const
816 /* We print a heading for every change of line span, hence for every
817 line span after the initial one. */
818 if (line_span_idx > 0)
819 return true;
821 /* We also do it for the initial span if the primary location of the
822 diagnostic is in a different span. */
823 if (m_exploc.line > (int)get_line_span (0)->m_last_line)
824 return true;
826 return false;
829 /* Get an expanded_location for the first location of interest within
830 the given line_span.
831 Used when printing a heading to indicate a new line span. */
833 expanded_location
834 layout::get_expanded_location (const line_span *line_span) const
836 /* Whenever possible, use the caret location. */
837 if (line_span->contains_line_p (m_exploc.line))
838 return m_exploc;
840 /* Otherwise, use the start of the first range that's present
841 within the line_span. */
842 for (unsigned int i = 0; i < m_layout_ranges.length (); i++)
844 const layout_range *lr = &m_layout_ranges[i];
845 if (line_span->contains_line_p (lr->m_start.m_line))
847 expanded_location exploc = m_exploc;
848 exploc.line = lr->m_start.m_line;
849 exploc.column = lr->m_start.m_column;
850 return exploc;
854 /* It should not be possible to have a line span that didn't
855 contain any of the layout_range instances. */
856 gcc_unreachable ();
857 return m_exploc;
860 /* We want to print the pertinent source code at a diagnostic. The
861 rich_location can contain multiple locations. This will have been
862 filtered into m_exploc (the caret for the primary location) and
863 m_layout_ranges, for those ranges within the same source file.
865 We will print a subset of the lines within the source file in question,
866 as a collection of "spans" of lines.
868 This function populates m_line_spans with an ordered, disjoint list of
869 the line spans of interest.
871 For example, if the primary caret location is on line 7, with ranges
872 covering lines 5-6 and lines 9-12:
875 005 |RANGE 0
876 006 |RANGE 0
877 007 |PRIMARY CARET
879 009 |RANGE 1
880 010 |RANGE 1
881 011 |RANGE 1
882 012 |RANGE 1
885 then we want two spans: lines 5-7 and lines 9-12. */
887 void
888 layout::calculate_line_spans ()
890 /* This should only be called once, by the ctor. */
891 gcc_assert (m_line_spans.length () == 0);
893 /* Populate tmp_spans with individual spans, for each of
894 m_exploc, and for m_layout_ranges. */
895 auto_vec<line_span> tmp_spans (1 + rich_location::MAX_RANGES);
896 tmp_spans.safe_push (line_span (m_exploc.line, m_exploc.line));
897 for (unsigned int i = 0; i < m_layout_ranges.length (); i++)
899 const layout_range *lr = &m_layout_ranges[i];
900 gcc_assert (lr->m_start.m_line <= lr->m_finish.m_line);
901 tmp_spans.safe_push (line_span (lr->m_start.m_line,
902 lr->m_finish.m_line));
905 /* Sort them. */
906 tmp_spans.qsort(line_span::comparator);
908 /* Now iterate through tmp_spans, copying into m_line_spans, and
909 combining where possible. */
910 gcc_assert (tmp_spans.length () > 0);
911 m_line_spans.safe_push (tmp_spans[0]);
912 for (unsigned int i = 1; i < tmp_spans.length (); i++)
914 line_span *current = &m_line_spans[m_line_spans.length () - 1];
915 const line_span *next = &tmp_spans[i];
916 gcc_assert (next->m_first_line >= current->m_first_line);
917 if (next->m_first_line <= current->m_last_line + 1)
919 /* We can merge them. */
920 if (next->m_last_line > current->m_last_line)
921 current->m_last_line = next->m_last_line;
923 else
925 /* No merger possible. */
926 m_line_spans.safe_push (*next);
930 /* Verify the result, in m_line_spans. */
931 gcc_assert (m_line_spans.length () > 0);
932 for (unsigned int i = 1; i < m_line_spans.length (); i++)
934 const line_span *prev = &m_line_spans[i - 1];
935 const line_span *next = &m_line_spans[i];
936 /* The individual spans must be sane. */
937 gcc_assert (prev->m_first_line <= prev->m_last_line);
938 gcc_assert (next->m_first_line <= next->m_last_line);
939 /* The spans must be ordered. */
940 gcc_assert (prev->m_first_line < next->m_first_line);
941 /* There must be a gap of at least one line between separate spans. */
942 gcc_assert ((prev->m_last_line + 1) < next->m_first_line);
946 /* Attempt to print line ROW of source code, potentially colorized at any
947 ranges.
948 Return true if the line was printed, populating *LBOUNDS_OUT.
949 Return false if the source line could not be read, leaving *LBOUNDS_OUT
950 untouched. */
952 bool
953 layout::print_source_line (int row, line_bounds *lbounds_out)
955 int line_width;
956 const char *line = location_get_source_line (m_exploc.file, row,
957 &line_width);
958 if (!line)
959 return false;
961 m_colorizer.set_normal_text ();
963 /* We will stop printing the source line at any trailing
964 whitespace. */
965 line_width = get_line_width_without_trailing_whitespace (line,
966 line_width);
967 line += m_x_offset;
969 pp_space (m_pp);
970 int first_non_ws = INT_MAX;
971 int last_non_ws = 0;
972 int column;
973 for (column = 1 + m_x_offset; column <= line_width; column++)
975 /* Assuming colorization is enabled for the caret and underline
976 characters, we may also colorize the associated characters
977 within the source line.
979 For frontends that generate range information, we color the
980 associated characters in the source line the same as the
981 carets and underlines in the annotation line, to make it easier
982 for the reader to see the pertinent code.
984 For frontends that only generate carets, we don't colorize the
985 characters above them, since this would look strange (e.g.
986 colorizing just the first character in a token). */
987 if (m_colorize_source_p)
989 bool in_range_p;
990 point_state state;
991 in_range_p = get_state_at_point (row, column,
992 0, INT_MAX,
993 &state);
994 if (in_range_p)
995 m_colorizer.set_range (state.range_idx);
996 else
997 m_colorizer.set_normal_text ();
999 char c = *line == '\t' ? ' ' : *line;
1000 if (c == '\0')
1001 c = ' ';
1002 if (c != ' ')
1004 last_non_ws = column;
1005 if (first_non_ws == INT_MAX)
1006 first_non_ws = column;
1008 pp_character (m_pp, c);
1009 line++;
1011 print_newline ();
1013 lbounds_out->m_first_non_ws = first_non_ws;
1014 lbounds_out->m_last_non_ws = last_non_ws;
1015 return true;
1018 /* Print a line consisting of the caret/underlines for the given
1019 source line. */
1021 void
1022 layout::print_annotation_line (int row, const line_bounds lbounds)
1024 int x_bound = get_x_bound_for_row (row, m_exploc.column,
1025 lbounds.m_last_non_ws);
1027 pp_space (m_pp);
1028 for (int column = 1 + m_x_offset; column < x_bound; column++)
1030 bool in_range_p;
1031 point_state state;
1032 in_range_p = get_state_at_point (row, column,
1033 lbounds.m_first_non_ws,
1034 lbounds.m_last_non_ws,
1035 &state);
1036 if (in_range_p)
1038 /* Within a range. Draw either the caret or an underline. */
1039 m_colorizer.set_range (state.range_idx);
1040 if (state.draw_caret_p)
1041 /* Draw the caret. */
1042 pp_character (m_pp, m_context->caret_chars[state.range_idx]);
1043 else
1044 pp_character (m_pp, '~');
1046 else
1048 /* Not in a range. */
1049 m_colorizer.set_normal_text ();
1050 pp_character (m_pp, ' ');
1053 print_newline ();
1056 /* If there are any fixit hints on source line ROW within RICHLOC, print them.
1057 They are printed in order, attempting to combine them onto lines, but
1058 starting new lines if necessary. */
1060 void
1061 layout::print_any_fixits (int row, const rich_location *richloc)
1063 int column = 0;
1064 for (unsigned int i = 0; i < richloc->get_num_fixit_hints (); i++)
1066 fixit_hint *hint = richloc->get_fixit_hint (i);
1067 if (hint->affects_line_p (m_exploc.file, row))
1069 /* For now we assume each fixit hint can only touch one line. */
1070 switch (hint->get_kind ())
1072 case fixit_hint::INSERT:
1074 fixit_insert *insert = static_cast <fixit_insert *> (hint);
1075 /* This assumes the insertion just affects one line. */
1076 int start_column
1077 = LOCATION_COLUMN (insert->get_location ());
1078 move_to_column (&column, start_column);
1079 m_colorizer.set_fixit_hint ();
1080 pp_string (m_pp, insert->get_string ());
1081 m_colorizer.set_normal_text ();
1082 column += insert->get_length ();
1084 break;
1086 case fixit_hint::REMOVE:
1088 fixit_remove *remove = static_cast <fixit_remove *> (hint);
1089 /* This assumes the removal just affects one line. */
1090 source_range src_range = remove->get_range ();
1091 int start_column = LOCATION_COLUMN (src_range.m_start);
1092 int finish_column = LOCATION_COLUMN (src_range.m_finish);
1093 move_to_column (&column, start_column);
1094 for (int column = start_column; column <= finish_column; column++)
1096 m_colorizer.set_fixit_hint ();
1097 pp_character (m_pp, '-');
1098 m_colorizer.set_normal_text ();
1101 break;
1103 case fixit_hint::REPLACE:
1105 fixit_replace *replace = static_cast <fixit_replace *> (hint);
1106 int start_column
1107 = LOCATION_COLUMN (replace->get_range ().m_start);
1108 move_to_column (&column, start_column);
1109 m_colorizer.set_fixit_hint ();
1110 pp_string (m_pp, replace->get_string ());
1111 m_colorizer.set_normal_text ();
1112 column += replace->get_length ();
1114 break;
1116 default:
1117 gcc_unreachable ();
1122 /* Add a trailing newline, if necessary. */
1123 move_to_column (&column, 0);
1126 /* Disable any colorization and emit a newline. */
1128 void
1129 layout::print_newline ()
1131 m_colorizer.set_normal_text ();
1132 pp_newline (m_pp);
1135 /* Return true if (ROW/COLUMN) is within a range of the layout.
1136 If it returns true, OUT_STATE is written to, with the
1137 range index, and whether we should draw the caret at
1138 (ROW/COLUMN) (as opposed to an underline). */
1140 bool
1141 layout::get_state_at_point (/* Inputs. */
1142 int row, int column,
1143 int first_non_ws, int last_non_ws,
1144 /* Outputs. */
1145 point_state *out_state)
1147 layout_range *range;
1148 int i;
1149 FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
1151 if (range->contains_point (row, column))
1153 out_state->range_idx = i;
1155 /* Are we at the range's caret? is it visible? */
1156 out_state->draw_caret_p = false;
1157 if (range->m_show_caret_p
1158 && row == range->m_caret.m_line
1159 && column == range->m_caret.m_column)
1160 out_state->draw_caret_p = true;
1162 /* Within a multiline range, don't display any underline
1163 in any leading or trailing whitespace on a line.
1164 We do display carets, however. */
1165 if (!out_state->draw_caret_p)
1166 if (column < first_non_ws || column > last_non_ws)
1167 return false;
1169 /* We are within a range. */
1170 return true;
1174 return false;
1177 /* Helper function for use by layout::print_line when printing the
1178 annotation line under the source line.
1179 Get the column beyond the rightmost one that could contain a caret or
1180 range marker, given that we stop rendering at trailing whitespace.
1181 ROW is the source line within the given file.
1182 CARET_COLUMN is the column of range 0's caret.
1183 LAST_NON_WS_COLUMN is the last column containing a non-whitespace
1184 character of source (as determined when printing the source line). */
1187 layout::get_x_bound_for_row (int row, int caret_column,
1188 int last_non_ws_column)
1190 int result = caret_column + 1;
1192 layout_range *range;
1193 int i;
1194 FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
1196 if (row >= range->m_start.m_line)
1198 if (range->m_finish.m_line == row)
1200 /* On the final line within a range; ensure that
1201 we render up to the end of the range. */
1202 if (result <= range->m_finish.m_column)
1203 result = range->m_finish.m_column + 1;
1205 else if (row < range->m_finish.m_line)
1207 /* Within a multiline range; ensure that we render up to the
1208 last non-whitespace column. */
1209 if (result <= last_non_ws_column)
1210 result = last_non_ws_column + 1;
1215 return result;
1218 /* Given *COLUMN as an x-coordinate, print spaces to position
1219 successive output at DEST_COLUMN, printing a newline if necessary,
1220 and updating *COLUMN. */
1222 void
1223 layout::move_to_column (int *column, int dest_column)
1225 /* Start a new line if we need to. */
1226 if (*column > dest_column)
1228 print_newline ();
1229 *column = 0;
1232 while (*column < dest_column)
1234 pp_space (m_pp);
1235 (*column)++;
1239 /* For debugging layout issues, render a ruler giving column numbers
1240 (after the 1-column indent). */
1242 void
1243 layout::show_ruler (int max_column) const
1245 /* Hundreds. */
1246 if (max_column > 99)
1248 pp_space (m_pp);
1249 for (int column = 1 + m_x_offset; column <= max_column; column++)
1250 if (0 == column % 10)
1251 pp_character (m_pp, '0' + (column / 100) % 10);
1252 else
1253 pp_space (m_pp);
1254 pp_newline (m_pp);
1257 /* Tens. */
1258 pp_space (m_pp);
1259 for (int column = 1 + m_x_offset; column <= max_column; column++)
1260 if (0 == column % 10)
1261 pp_character (m_pp, '0' + (column / 10) % 10);
1262 else
1263 pp_space (m_pp);
1264 pp_newline (m_pp);
1266 /* Units. */
1267 pp_space (m_pp);
1268 for (int column = 1 + m_x_offset; column <= max_column; column++)
1269 pp_character (m_pp, '0' + (column % 10));
1270 pp_newline (m_pp);
1273 } /* End of anonymous namespace. */
1275 /* Print the physical source code corresponding to the location of
1276 this diagnostic, with additional annotations. */
1278 void
1279 diagnostic_show_locus (diagnostic_context * context,
1280 rich_location *richloc,
1281 diagnostic_t diagnostic_kind)
1283 pp_newline (context->printer);
1285 location_t loc = richloc->get_loc ();
1286 /* Do nothing if source-printing has been disabled. */
1287 if (!context->show_caret)
1288 return;
1290 /* Don't attempt to print source for UNKNOWN_LOCATION and for builtins. */
1291 if (loc <= BUILTINS_LOCATION)
1292 return;
1294 /* Don't print the same source location twice in a row, unless we have
1295 fix-it hints. */
1296 if (loc == context->last_location
1297 && richloc->get_num_fixit_hints () == 0)
1298 return;
1300 context->last_location = loc;
1302 const char *saved_prefix = pp_get_prefix (context->printer);
1303 pp_set_prefix (context->printer, NULL);
1305 layout layout (context, richloc, diagnostic_kind);
1306 for (int line_span_idx = 0; line_span_idx < layout.get_num_line_spans ();
1307 line_span_idx++)
1309 const line_span *line_span = layout.get_line_span (line_span_idx);
1310 if (layout.print_heading_for_line_span_index_p (line_span_idx))
1312 expanded_location exploc = layout.get_expanded_location (line_span);
1313 context->start_span (context, exploc);
1315 int last_line = line_span->get_last_line ();
1316 for (int row = line_span->get_first_line (); row <= last_line; row++)
1318 /* Print the source line, followed by an annotation line
1319 consisting of any caret/underlines, then any fixits.
1320 If the source line can't be read, print nothing. */
1321 line_bounds lbounds;
1322 if (layout.print_source_line (row, &lbounds))
1324 layout.print_annotation_line (row, lbounds);
1325 layout.print_any_fixits (row, richloc);
1330 pp_set_prefix (context->printer, saved_prefix);
1333 #if CHECKING_P
1335 namespace selftest {
1337 /* Selftests for diagnostic_show_locus. */
1339 /* Convenience subclass of diagnostic_context for testing
1340 diagnostic_show_locus. */
1342 class test_diagnostic_context : public diagnostic_context
1344 public:
1345 test_diagnostic_context ()
1347 diagnostic_initialize (this, 0);
1348 show_caret = true;
1350 ~test_diagnostic_context ()
1352 diagnostic_finish (this);
1356 /* Verify that diagnostic_show_locus works sanely on UNKNOWN_LOCATION. */
1358 static void
1359 test_diagnostic_show_locus_unknown_location ()
1361 test_diagnostic_context dc;
1362 rich_location richloc (line_table, UNKNOWN_LOCATION);
1363 diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1364 ASSERT_STREQ ("\n", pp_formatted_text (dc.printer));
1367 /* Verify that diagnostic_show_locus works sanely for various
1368 single-line cases.
1370 All of these work on the following 1-line source file:
1371 .0000000001111111
1372 .1234567890123456
1373 "foo = bar.field;\n"
1374 which is set up by test_diagnostic_show_locus_one_liner and calls
1375 them. */
1377 /* Just a caret. */
1379 static void
1380 test_one_liner_simple_caret ()
1382 test_diagnostic_context dc;
1383 location_t caret = linemap_position_for_column (line_table, 10);
1384 rich_location richloc (line_table, caret);
1385 diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1386 ASSERT_STREQ ("\n"
1387 " foo = bar.field;\n"
1388 " ^\n",
1389 pp_formatted_text (dc.printer));
1392 /* Caret and range. */
1394 static void
1395 test_one_liner_caret_and_range ()
1397 test_diagnostic_context dc;
1398 location_t caret = linemap_position_for_column (line_table, 10);
1399 location_t start = linemap_position_for_column (line_table, 7);
1400 location_t finish = linemap_position_for_column (line_table, 15);
1401 location_t loc = make_location (caret, start, finish);
1402 rich_location richloc (line_table, loc);
1403 diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1404 ASSERT_STREQ ("\n"
1405 " foo = bar.field;\n"
1406 " ~~~^~~~~~\n",
1407 pp_formatted_text (dc.printer));
1410 /* Multiple ranges and carets. */
1412 static void
1413 test_one_liner_multiple_carets_and_ranges ()
1415 test_diagnostic_context dc;
1416 location_t foo
1417 = make_location (linemap_position_for_column (line_table, 2),
1418 linemap_position_for_column (line_table, 1),
1419 linemap_position_for_column (line_table, 3));
1420 dc.caret_chars[0] = 'A';
1422 location_t bar
1423 = make_location (linemap_position_for_column (line_table, 8),
1424 linemap_position_for_column (line_table, 7),
1425 linemap_position_for_column (line_table, 9));
1426 dc.caret_chars[1] = 'B';
1428 location_t field
1429 = make_location (linemap_position_for_column (line_table, 13),
1430 linemap_position_for_column (line_table, 11),
1431 linemap_position_for_column (line_table, 15));
1432 dc.caret_chars[2] = 'C';
1434 rich_location richloc (line_table, foo);
1435 richloc.add_range (bar, true);
1436 richloc.add_range (field, true);
1437 diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1438 ASSERT_STREQ ("\n"
1439 " foo = bar.field;\n"
1440 " ~A~ ~B~ ~~C~~\n",
1441 pp_formatted_text (dc.printer));
1444 /* Insertion fix-it hint: adding an "&" to the front of "bar.field". */
1446 static void
1447 test_one_liner_fixit_insert ()
1449 test_diagnostic_context dc;
1450 location_t caret = linemap_position_for_column (line_table, 7);
1451 rich_location richloc (line_table, caret);
1452 richloc.add_fixit_insert (caret, "&");
1453 diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1454 ASSERT_STREQ ("\n"
1455 " foo = bar.field;\n"
1456 " ^\n"
1457 " &\n",
1458 pp_formatted_text (dc.printer));
1461 /* Removal fix-it hint: removal of the ".field". */
1463 static void
1464 test_one_liner_fixit_remove ()
1466 test_diagnostic_context dc;
1467 location_t start = linemap_position_for_column (line_table, 10);
1468 location_t finish = linemap_position_for_column (line_table, 15);
1469 location_t dot = make_location (start, start, finish);
1470 rich_location richloc (line_table, dot);
1471 source_range range;
1472 range.m_start = start;
1473 range.m_finish = finish;
1474 richloc.add_fixit_remove (range);
1475 diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1476 ASSERT_STREQ ("\n"
1477 " foo = bar.field;\n"
1478 " ^~~~~~\n"
1479 " ------\n",
1480 pp_formatted_text (dc.printer));
1483 /* Replace fix-it hint: replacing "field" with "m_field". */
1485 static void
1486 test_one_liner_fixit_replace ()
1488 test_diagnostic_context dc;
1489 location_t start = linemap_position_for_column (line_table, 11);
1490 location_t finish = linemap_position_for_column (line_table, 15);
1491 location_t field = make_location (start, start, finish);
1492 rich_location richloc (line_table, field);
1493 source_range range;
1494 range.m_start = start;
1495 range.m_finish = finish;
1496 richloc.add_fixit_replace (range, "m_field");
1497 diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1498 ASSERT_STREQ ("\n"
1499 " foo = bar.field;\n"
1500 " ^~~~~\n"
1501 " m_field\n",
1502 pp_formatted_text (dc.printer));
1505 /* Run the various one-liner tests. */
1507 static void
1508 test_diagnostic_show_locus_one_liner (const line_table_case &case_)
1510 /* Create a tempfile and write some text to it.
1511 ....................0000000001111111.
1512 ....................1234567890123456. */
1513 const char *content = "foo = bar.field;\n";
1514 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
1515 line_table_test ltt (case_);
1517 linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
1519 location_t line_end = linemap_position_for_column (line_table, 16);
1521 /* Don't attempt to run the tests if column data might be unavailable. */
1522 if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
1523 return;
1525 ASSERT_STREQ (tmp.get_filename (), LOCATION_FILE (line_end));
1526 ASSERT_EQ (1, LOCATION_LINE (line_end));
1527 ASSERT_EQ (16, LOCATION_COLUMN (line_end));
1529 test_one_liner_simple_caret ();
1530 test_one_liner_caret_and_range ();
1531 test_one_liner_multiple_carets_and_ranges ();
1532 test_one_liner_fixit_insert ();
1533 test_one_liner_fixit_remove ();
1534 test_one_liner_fixit_replace ();
1537 /* Run all of the selftests within this file. */
1539 void
1540 diagnostic_show_locus_c_tests ()
1542 test_range_contains_point_for_single_point ();
1543 test_range_contains_point_for_single_line ();
1544 test_range_contains_point_for_multiple_lines ();
1546 test_get_line_width_without_trailing_whitespace ();
1548 test_diagnostic_show_locus_unknown_location ();
1550 for_each_line_table_case (test_diagnostic_show_locus_one_liner);
1553 } // namespace selftest
1555 #endif /* #if CHECKING_P */