From: David Malcolm Date: Wed, 31 Aug 2016 00:35:01 +0000 (+0000) Subject: Remove arbitrary limits from rich_location X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b816477a5ad7277b3a588e9a58cbcd764152b8d2;p=gcc.git Remove arbitrary limits from rich_location This patch eliminates the hard-coded limits within rich_location (up to 3 ranges, up to 2 fixits). The common case is still handled by embedding the values inside rich_location - it only uses dynamic allocation if these limits are exceeded, so creation of rich_location instances on the stack should still be fast. This is implemented via a new container class, semi_embedded_vec . gcc/ChangeLog: * diagnostic-show-locus.c (colorizer::begin_state): Support more than 3 ranges per diagnostic by alternating between color 1 and color 2. (layout::layout): Replace use of rich_location::MAX_RANGES with richloc->get_num_locations (). (layout::calculate_line_spans): Replace use of rich_location::MAX_RANGES with m_layout_ranges.length (). (layout::print_annotation_line): Handle arbitrary numbers of ranges in caret-printing by defaulting to '^'. (selftest::test_one_liner_many_fixits): New function. (test_diagnostic_show_locus_one_liner): Call it. * diagnostic.c (diagnostic_initialize): Update for renaming of rich_location::MAX_RANGES to rich_location::STATICALLY_ALLOCATED_RANGES. * diagnostic.h (struct diagnostic_context): Likewise. gcc/testsuite/ChangeLog: * gcc.dg/plugin/diagnostic-test-show-locus-bw.c (test_many_nested_locations): New function. * gcc.dg/plugin/diagnostic_plugin_test_show_locus.c (test_show_locus): Handle "test_many_nested_locations". libcpp/ChangeLog: * include/line-map.h (class semi_embedded_vec): New class. (semi_embedded_vec::semi_embedded_vec): New ctor. (semi_embedded_vec::~semi_embedded_vec): New dtor. (semi_embedded_vec::operator[]): New methods. (semi_embedded_vec::push): New method. (semi_embedded_vec::truncate): New method. (rich_location::get_num_locations): Reimplement in terms of m_ranges. (rich_location::get_range): Make non-inline. (rich_location::get_num_fixit_hints): Reimplement in terms of m_fixit_hints. (rich_location::add_fixit): New function. (rich_location::MAX_RANGES): Rename to... (rich_location::STATICALLY_ALLOCATED_RANGES): ...this. (rich_location::MAX_FIXIT_HINTS): Rename to... (rich_location::STATICALLY_ALLOCATED_RANGES): ...this, and make private. (rich_location::m_num_ranges): Eliminate in favor of... (rich_location::m_ranges): ...this, converting from a fixed-size array to a semi_embedded_vec. (rich_location::m_num_fixit_hints): Eliminate in favor of... (rich_location::m_fixit_hints): ...this, converting from a fixed-size array to a semi_embedded_vec. * line-map.c (rich_location::rich_location): Update for above changes. (rich_location::~rich_location): Likewise. (rich_location::get_loc): Likewise. (rich_location::get_range): New methods. (rich_location::add_range): Update for above changes. (rich_location::set_range): Likewise. (rich_location::add_fixit_insert): Likewise. (rich_location::add_fixit_replace): Likewise. (rich_location::get_last_fixit_hint): Likewise. (rich_location::reject_impossible_fixit): Likewise. (rich_location::add_fixit): New method. From-SVN: r239879 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fa764e86425..54f2f7a33ba 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2016-08-30 David Malcolm + + * diagnostic-show-locus.c (colorizer::begin_state): Support more + than 3 ranges per diagnostic by alternating between color 1 and + color 2. + (layout::layout): Replace use of rich_location::MAX_RANGES + with richloc->get_num_locations (). + (layout::calculate_line_spans): Replace use of + rich_location::MAX_RANGES with m_layout_ranges.length (). + (layout::print_annotation_line): Handle arbitrary numbers of + ranges in caret-printing by defaulting to '^'. + (selftest::test_one_liner_many_fixits): New function. + (test_diagnostic_show_locus_one_liner): Call it. + * diagnostic.c (diagnostic_initialize): Update for renaming + of rich_location::MAX_RANGES to + rich_location::STATICALLY_ALLOCATED_RANGES. + * diagnostic.h (struct diagnostic_context): Likewise. + 2016-08-30 David Malcolm * selftest.c (selftest::named_temp_file::named_temp_file): New diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c index 60f68204df8..a22a660543a 100644 --- a/gcc/diagnostic-show-locus.c +++ b/gcc/diagnostic-show-locus.c @@ -317,8 +317,12 @@ colorizer::begin_state (int state) break; default: - /* We don't expect more than 3 ranges per diagnostic. */ - gcc_unreachable (); + /* For ranges beyond 2, alternate between color 1 and color 2. */ + { + gcc_assert (state > 2); + pp_string (m_context->printer, + state % 2 ? m_range1 : m_range2); + } break; } } @@ -720,8 +724,8 @@ layout::layout (diagnostic_context * context, m_exploc (richloc->get_expanded_location (0)), m_colorizer (context, diagnostic_kind), m_colorize_source_p (context->colorize_source_p), - m_layout_ranges (rich_location::MAX_RANGES), - m_line_spans (1 + rich_location::MAX_RANGES), + m_layout_ranges (richloc->get_num_locations ()), + m_line_spans (1 + richloc->get_num_locations ()), m_x_offset (0) { source_location primary_loc = richloc->get_range (0)->m_loc; @@ -904,7 +908,7 @@ layout::calculate_line_spans () /* Populate tmp_spans with individual spans, for each of m_exploc, and for m_layout_ranges. */ - auto_vec tmp_spans (1 + rich_location::MAX_RANGES); + auto_vec tmp_spans (1 + m_layout_ranges.length ()); tmp_spans.safe_push (line_span (m_exploc.line, m_exploc.line)); for (unsigned int i = 0; i < m_layout_ranges.length (); i++) { @@ -1050,8 +1054,15 @@ layout::print_annotation_line (int row, const line_bounds lbounds) /* Within a range. Draw either the caret or an underline. */ m_colorizer.set_range (state.range_idx); if (state.draw_caret_p) - /* Draw the caret. */ - pp_character (m_pp, m_context->caret_chars[state.range_idx]); + { + /* Draw the caret. */ + char caret_char; + if (state.range_idx < rich_location::STATICALLY_ALLOCATED_RANGES) + caret_char = m_context->caret_chars[state.range_idx]; + else + caret_char = '^'; + pp_character (m_pp, caret_char); + } else pp_character (m_pp, '~'); } @@ -1654,6 +1665,44 @@ test_one_liner_fixit_validation_adhoc_locations () } } +/* Ensure that we can add an arbitrary number of fix-it hints to a + rich_location. */ + +static void +test_one_liner_many_fixits () +{ + test_diagnostic_context dc; + location_t equals = linemap_position_for_column (line_table, 5); + rich_location richloc (line_table, equals); + for (int i = 0; i < 19; i++) + richloc.add_fixit_insert ("a"); + ASSERT_EQ (19, richloc.get_num_fixit_hints ()); + diagnostic_show_locus (&dc, &richloc, DK_ERROR); + ASSERT_STREQ ("\n" + " foo = bar.field;\n" + " ^\n" + " a\n" + " a\n" + " a\n" + " a\n" + " a\n" + " a\n" + " a\n" + " a\n" + " a\n" + " a\n" + " a\n" + " a\n" + " a\n" + " a\n" + " a\n" + " a\n" + " a\n" + " a\n" + " a\n", + pp_formatted_text (dc.printer)); +} + /* Run the various one-liner tests. */ static void @@ -1687,6 +1736,7 @@ test_diagnostic_show_locus_one_liner (const line_table_case &case_) test_one_liner_fixit_replace_non_equal_range (); test_one_liner_fixit_replace_equal_secondary_range (); test_one_liner_fixit_validation_adhoc_locations (); + test_one_liner_many_fixits (); } /* Verify that fix-it hints are appropriately consolidated. diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index b47da383fc3..47b4c79ebcc 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -147,7 +147,7 @@ diagnostic_initialize (diagnostic_context *context, int n_opts) context->classify_diagnostic[i] = DK_UNSPECIFIED; context->show_caret = false; diagnostic_set_caret_max_width (context, pp_line_cutoff (context->printer)); - for (i = 0; i < rich_location::MAX_RANGES; i++) + for (i = 0; i < rich_location::STATICALLY_ALLOCATED_RANGES; i++) context->caret_chars[i] = '^'; context->show_option_requested = false; context->abort_on_error = false; diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 104e39c868a..0727644d96b 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -109,7 +109,7 @@ struct diagnostic_context int caret_max_width; /* Character used for caret diagnostics. */ - char caret_chars[rich_location::MAX_RANGES]; + char caret_chars[rich_location::STATICALLY_ALLOCATED_RANGES]; /* True if we should print the command line option which controls each diagnostic, if known. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6e3b70662d0..cf97b393f12 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2016-08-30 David Malcolm + + * gcc.dg/plugin/diagnostic-test-show-locus-bw.c + (test_many_nested_locations): New function. + * gcc.dg/plugin/diagnostic_plugin_test_show_locus.c + (test_show_locus): Handle "test_many_nested_locations". + 2016-08-30 David Malcolm * g++.dg/template/double-greater-than-fixit.C: New test case. diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c index 2748fa1f280..e8112bfa3a5 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c @@ -205,3 +205,47 @@ int test_percent_q_plus_d (void) { dg-end-multiline-output "" } */ return local; } + +/* Test of many nested locations and fixits. */ + +void test_many_nested_locations (void) +{ + /* { dg-warning "test of 70 locations" } + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. Ut enim ad minim veniam, quis nostrud exercitation + ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis + aute irure dolor in reprehenderit in voluptate velit esse cillum + dolore eu fugiat nulla pariatur. Excepteur sint occaecat + cupidatat non proident, sunt in culpa qui officia deserunt + mollit anim id est laborum. + */ +/* { dg-begin-multiline-output "" } + /* + ^ + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + ^~~~~ ^~~~~ ^~~~~ ^~~ ^~~~ ^~~~~~~~~~~ ^~~~~~~~~~ ^~~~ + LOREM IPSUM DOLOR SIT AMET CONSECTETUR ADIPISCING ELIT + sed do eiusmod tempor incididunt ut labore et dolore magna + ^~~ ^~ ^~~~~~~ ^~~~~~ ^~~~~~~~~~ ^~ ^~~~~~ ^~ ^~~~~~ ^~~~~ + SED DO EIUSMOD TEMPOR INCIDIDUNT UT LABORE ET DOLORE MAGNA + aliqua. Ut enim ad minim veniam, quis nostrud exercitation + ^~~~~~ ^~ ^~~~ ^~ ^~~~~ ^~~~~~ ^~~~ ^~~~~~~ ^~~~~~~~~~~~ + ALIQUA UT ENIM AD MINIM VENIAM QUIS NOSTRUD EXERCITATION + ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis + ^~~~~~~ ^~~~~~~ ^~~~ ^~ ^~~~~~~ ^~ ^~ ^~~~~~~ ^~~~~~~~~ ^~~~ + ULLAMCO LABORIS NISI UT ALIQUIP EX EA COMMODO CONSEQUAT DUIS + aute irure dolor in reprehenderit in voluptate velit esse cillum + ^~~~ ^~~~~ ^~~~~ ^~ ^~~~~~~~~~~~~ ^~ ^~~~~~~~~ ^~~~~ ^~~~ ^~~~~~ + AUTE IRURE DOLOR IN REPREHENDERIT IN VOLUPTATE VELIT ESSE CILLUM + dolore eu fugiat nulla pariatur. Excepteur sint occaecat + ^~~~~~ ^~ ^~~~~~ ^~~~~ ^~~~~~~~ ^~~~~~~~~ ^~~~ ^~~~~~~~ + DOLORE EU FUGIAT NULLA PARIATUR EXCEPTEUR SINT OCCAECAT + cupidatat non proident, sunt in culpa qui officia deserunt + ^~~~~~~~~ ^~~ ^~~~~~~~ ^~~~ ^~ ^~~~~ ^~~ ^~~~~~~ ^~~~~~~~ + CUPIDATAT NON PROIDENT SUNT IN CULPA QUI OFFICIA DESERUNT + mollit anim id est laborum. + ^~~~~~ ^~~~ ^~ ^~~ ^~~~~~~ + MOLLIT ANIM ID EST LABORUM + { dg-end-multiline-output "" } */ +} diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c index d57400d90ff..ea28f046e8d 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c @@ -325,6 +325,59 @@ test_show_locus (function *fun) warning_at (input_location, 0, "example of plus in format code for %q+D", local); } + + /* Example of many locations and many fixits. + Underline (separately) every word in a comment, and convert them + to upper case. */ + if (0 == strcmp (fnname, "test_many_nested_locations")) + { + const char *file = LOCATION_FILE (fnstart); + const int start_line = fnstart_line + 2; + const int finish_line = start_line + 7; + location_t loc = get_loc (start_line - 1, 2); + rich_location richloc (line_table, loc); + for (int line = start_line; line <= finish_line; line++) + { + int line_size; + const char *content = location_get_source_line (file, line, + &line_size); + gcc_assert (content); + /* Split line up into words. */ + for (int idx = 0; idx < line_size; idx++) + { + if (ISALPHA (content[idx])) + { + int start_idx = idx; + while (idx < line_size && ISALPHA (content[idx])) + idx++; + if (idx == line_size || !ISALPHA (content[idx])) + { + location_t start_of_word = get_loc (line, start_idx); + location_t end_of_word = get_loc (line, idx - 1); + location_t word + = make_location (start_of_word, start_of_word, + end_of_word); + richloc.add_range (word, true); + + /* Add a fixit, converting to upper case. */ + char *copy = xstrndup (content + start_idx, + idx - start_idx); + for (char *ch = copy; *ch; ch++) + *ch = TOUPPER (*ch); + richloc.add_fixit_replace (word, copy); + free (copy); + } + } + } + } + /* Verify that we added enough locations to fully exercise + rich_location. We want to exceed both the + statically-allocated buffer in class rich_location, + and then trigger a reallocation of the dynamic buffer. */ + gcc_assert (richloc.get_num_locations () > 3 + (2 * 16)); + warning_at_rich_loc (&richloc, 0, "test of %i locations", + richloc.get_num_locations ()); + } } unsigned int diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index a753033b826..595d6ca4cca 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,42 @@ +2016-08-30 David Malcolm + + * include/line-map.h (class semi_embedded_vec): New class. + (semi_embedded_vec::semi_embedded_vec): New ctor. + (semi_embedded_vec::~semi_embedded_vec): New + dtor. + (semi_embedded_vec::operator[]): New methods. + (semi_embedded_vec::push): New method. + (semi_embedded_vec::truncate): New method. + (rich_location::get_num_locations): Reimplement in terms of + m_ranges. + (rich_location::get_range): Make non-inline. + (rich_location::get_num_fixit_hints): Reimplement in terms of + m_fixit_hints. + (rich_location::add_fixit): New function. + (rich_location::MAX_RANGES): Rename to... + (rich_location::STATICALLY_ALLOCATED_RANGES): ...this. + (rich_location::MAX_FIXIT_HINTS): Rename to... + (rich_location::STATICALLY_ALLOCATED_RANGES): ...this, and make + private. + (rich_location::m_num_ranges): Eliminate in favor of... + (rich_location::m_ranges): ...this, converting from a fixed-size + array to a semi_embedded_vec. + (rich_location::m_num_fixit_hints): Eliminate in favor of... + (rich_location::m_fixit_hints): ...this, converting from a + fixed-size array to a semi_embedded_vec. + * line-map.c (rich_location::rich_location): Update for above + changes. + (rich_location::~rich_location): Likewise. + (rich_location::get_loc): Likewise. + (rich_location::get_range): New methods. + (rich_location::add_range): Update for above changes. + (rich_location::set_range): Likewise. + (rich_location::add_fixit_insert): Likewise. + (rich_location::add_fixit_replace): Likewise. + (rich_location::get_last_fixit_hint): Likewise. + (rich_location::reject_impossible_fixit): Likewise. + (rich_location::add_fixit): New method. + 2016-08-30 David Malcolm * include/line-map.h (rich_location::add_fixit_insert): Add diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index 122e4742ed3..0c95b292599 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -1288,6 +1288,128 @@ struct location_range bool m_show_caret_p; }; +/* A partially-embedded vec for use within rich_location for storing + ranges and fix-it hints. + + Elements [0..NUM_EMBEDDED) are allocated within m_embed, after + that they are within the dynamically-allocated m_extra. + + This allows for static allocation in the common case, whilst + supporting the rarer case of an arbitrary number of elements. + + Dynamic allocation is not performed unless it's needed. */ + +template +class semi_embedded_vec +{ + public: + semi_embedded_vec (); + ~semi_embedded_vec (); + + unsigned int count () const { return m_num; } + T& operator[] (int idx); + const T& operator[] (int idx) const; + + void push (const T&); + void truncate (int len); + + private: + int m_num; + T m_embedded[NUM_EMBEDDED]; + int m_alloc; + T *m_extra; +}; + +/* Constructor for semi_embedded_vec. In particular, no dynamic allocation + is done. */ + +template +semi_embedded_vec::semi_embedded_vec () +: m_num (0), m_alloc (0), m_extra (NULL) +{ +} + +/* semi_embedded_vec's dtor. Release any dynamically-allocated memory. */ + +template +semi_embedded_vec::~semi_embedded_vec () +{ + XDELETEVEC (m_extra); +} + +/* Look up element IDX, mutably. */ + +template +T& +semi_embedded_vec::operator[] (int idx) +{ + linemap_assert (idx < m_num); + if (idx < NUM_EMBEDDED) + return m_embedded[idx]; + else + { + linemap_assert (m_extra != NULL); + return m_extra[idx - NUM_EMBEDDED]; + } +} + +/* Look up element IDX (const). */ + +template +const T& +semi_embedded_vec::operator[] (int idx) const +{ + linemap_assert (idx < m_num); + if (idx < NUM_EMBEDDED) + return m_embedded[idx]; + else + { + linemap_assert (m_extra != NULL); + return m_extra[idx - NUM_EMBEDDED]; + } +} + +/* Append VALUE to the end of the semi_embedded_vec. */ + +template +void +semi_embedded_vec::push (const T& value) +{ + int idx = m_num++; + if (idx < NUM_EMBEDDED) + m_embedded[idx] = value; + else + { + /* Offset "idx" to be an index within m_extra. */ + idx -= NUM_EMBEDDED; + if (NULL == m_extra) + { + linemap_assert (m_alloc == 0); + m_alloc = 16; + m_extra = XNEWVEC (T, m_alloc); + } + else if (idx >= m_alloc) + { + linemap_assert (m_alloc > 0); + m_alloc *= 2; + m_extra = XRESIZEVEC (T, m_extra, m_alloc); + } + linemap_assert (m_extra); + linemap_assert (idx < m_alloc); + m_extra[idx] = value; + } +} + +/* Truncate to length LEN. No deallocation is performed. */ + +template +void +semi_embedded_vec::truncate (int len) +{ + linemap_assert (len <= m_num); + m_num = len; +} + class fixit_hint; class fixit_insert; class fixit_remove; @@ -1387,13 +1509,10 @@ class rich_location set_range (line_maps *set, unsigned int idx, source_location loc, bool show_caret_p); - unsigned int get_num_locations () const { return m_num_ranges; } + unsigned int get_num_locations () const { return m_ranges.count (); } - location_range *get_range (unsigned int idx) - { - linemap_assert (idx < m_num_ranges); - return &m_ranges[idx]; - } + const location_range *get_range (unsigned int idx) const; + location_range *get_range (unsigned int idx); expanded_location get_expanded_location (unsigned int idx); @@ -1446,29 +1565,29 @@ class rich_location add_fixit_replace (source_range src_range, const char *new_content); - unsigned int get_num_fixit_hints () const { return m_num_fixit_hints; } + unsigned int get_num_fixit_hints () const { return m_fixit_hints.count (); } fixit_hint *get_fixit_hint (int idx) const { return m_fixit_hints[idx]; } fixit_hint *get_last_fixit_hint () const; private: bool reject_impossible_fixit (source_location where); + void add_fixit (fixit_hint *hint); public: - static const int MAX_RANGES = 3; - static const int MAX_FIXIT_HINTS = 2; + static const int STATICALLY_ALLOCATED_RANGES = 3; protected: line_maps *m_line_table; - unsigned int m_num_ranges; - location_range m_ranges[MAX_RANGES]; + semi_embedded_vec m_ranges; int m_column_override; bool m_have_expanded_location; expanded_location m_expanded_location; - unsigned int m_num_fixit_hints; - fixit_hint *m_fixit_hints[MAX_FIXIT_HINTS]; + static const int MAX_STATIC_FIXIT_HINTS = 2; + semi_embedded_vec m_fixit_hints; + bool m_seen_impossible_fixit; }; diff --git a/libcpp/line-map.c b/libcpp/line-map.c index 318932646a9..72549ba0732 100644 --- a/libcpp/line-map.c +++ b/libcpp/line-map.c @@ -1983,10 +1983,10 @@ source_range::intersects_line_p (const char *file, int line) const rich_location::rich_location (line_maps *set, source_location loc) : m_line_table (set), - m_num_ranges (0), + m_ranges (), m_column_override (0), m_have_expanded_location (false), - m_num_fixit_hints (0), + m_fixit_hints (), m_seen_impossible_fixit (false) { add_range (loc, true); @@ -1996,8 +1996,8 @@ rich_location::rich_location (line_maps *set, source_location loc) : rich_location::~rich_location () { - for (unsigned int i = 0; i < m_num_fixit_hints; i++) - delete m_fixit_hints[i]; + for (unsigned int i = 0; i < m_fixit_hints.count (); i++) + delete get_fixit_hint (i); } /* Get location IDX within this rich_location. */ @@ -2005,8 +2005,24 @@ rich_location::~rich_location () source_location rich_location::get_loc (unsigned int idx) const { - linemap_assert (idx < m_num_ranges); - return m_ranges[idx].m_loc; + const location_range *locrange = get_range (idx); + return locrange->m_loc; +} + +/* Get range IDX within this rich_location. */ + +const location_range * +rich_location::get_range (unsigned int idx) const +{ + return &m_ranges[idx]; +} + +/* Mutable access to range IDX within this rich_location. */ + +location_range * +rich_location::get_range (unsigned int idx) +{ + return &m_ranges[idx]; } /* Expand location IDX within this rich_location. */ @@ -2049,11 +2065,10 @@ rich_location::override_column (int column) void rich_location::add_range (source_location loc, bool show_caret_p) { - linemap_assert (m_num_ranges < MAX_RANGES); - - location_range *range = &m_ranges[m_num_ranges++]; - range->m_loc = loc; - range->m_show_caret_p = show_caret_p; + location_range range; + range.m_loc = loc; + range.m_show_caret_p = show_caret_p; + m_ranges.push (range); } /* Add or overwrite the location given by IDX, setting its location to LOC, @@ -2073,19 +2088,18 @@ void rich_location::set_range (line_maps * /*set*/, unsigned int idx, source_location loc, bool show_caret_p) { - linemap_assert (idx < MAX_RANGES); - /* We can either overwrite an existing range, or add one exactly on the end of the array. */ - linemap_assert (idx <= m_num_ranges); - - location_range *locrange = &m_ranges[idx]; - locrange->m_loc = loc; - locrange->m_show_caret_p = show_caret_p; + linemap_assert (idx <= m_ranges.count ()); - /* Are we adding a range onto the end? */ - if (idx == m_num_ranges) - m_num_ranges = idx + 1; + if (idx == m_ranges.count ()) + add_range (loc, show_caret_p); + else + { + location_range *locrange = get_range (idx); + locrange->m_loc = loc; + locrange->m_show_caret_p = show_caret_p; + } if (idx == 0) /* Mark any cached value here as dirty. */ @@ -2114,10 +2128,7 @@ rich_location::add_fixit_insert (source_location where, if (reject_impossible_fixit (where)) return; - - linemap_assert (m_num_fixit_hints < MAX_FIXIT_HINTS); - m_fixit_hints[m_num_fixit_hints++] - = new fixit_insert (where, new_content); + add_fixit (new fixit_insert (where, new_content)); } /* Methods for adding removal fix-it hints. */ @@ -2217,8 +2228,6 @@ void rich_location::add_fixit_replace (source_range src_range, const char *new_content) { - linemap_assert (m_num_fixit_hints < MAX_FIXIT_HINTS); - src_range.m_start = get_pure_location (m_line_table, src_range.m_start); src_range.m_finish = get_pure_location (m_line_table, src_range.m_finish); @@ -2229,14 +2238,11 @@ rich_location::add_fixit_replace (source_range src_range, /* Consolidate neighboring fixits. */ fixit_hint *prev = get_last_fixit_hint (); - if (m_num_fixit_hints > 0) - { - if (prev->maybe_append_replace (m_line_table, src_range, new_content)) - return; - } + if (prev) + if (prev->maybe_append_replace (m_line_table, src_range, new_content)) + return; - m_fixit_hints[m_num_fixit_hints++] - = new fixit_replace (src_range, new_content); + add_fixit (new fixit_replace (src_range, new_content)); } /* Get the last fix-it hint within this rich_location, or NULL if none. */ @@ -2244,8 +2250,8 @@ rich_location::add_fixit_replace (source_range src_range, fixit_hint * rich_location::get_last_fixit_hint () const { - if (m_num_fixit_hints > 0) - return m_fixit_hints[m_num_fixit_hints - 1]; + if (m_fixit_hints.count () > 0) + return get_fixit_hint (m_fixit_hints.count () - 1); else return NULL; } @@ -2275,13 +2281,21 @@ rich_location::reject_impossible_fixit (source_location where) m_seen_impossible_fixit = true; /* Purge the rich_location of any fix-its that were already added. */ - for (unsigned int i = 0; i < m_num_fixit_hints; i++) - delete m_fixit_hints[i]; - m_num_fixit_hints = 0; + for (unsigned int i = 0; i < m_fixit_hints.count (); i++) + delete get_fixit_hint (i); + m_fixit_hints.truncate (0); return true; } +/* Add HINT to the fix-it hints in this rich_location. */ + +void +rich_location::add_fixit (fixit_hint *hint) +{ + m_fixit_hints.push (hint); +} + /* class fixit_insert. */ fixit_insert::fixit_insert (source_location where,