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 <T, N>.

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<T, NUM_EMBEDDED>::semi_embedded_vec): New ctor.
	(semi_embedded_vec<T, NUM_EMBEDDED>::~semi_embedded_vec): New
	dtor.
	(semi_embedded_vec<T, NUM_EMBEDDED>::operator[]): New methods.
	(semi_embedded_vec<T, NUM_EMBEDDED>::push): New method.
	(semi_embedded_vec<T, NUM_EMBEDDED>::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
This commit is contained in:
David Malcolm 2016-08-31 00:35:01 +00:00 committed by David Malcolm
parent fb8e9c5e8e
commit b816477a5a
10 changed files with 405 additions and 61 deletions

View file

@ -1,3 +1,21 @@
2016-08-30 David Malcolm <dmalcolm@redhat.com>
* 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 <dmalcolm@redhat.com>
* selftest.c (selftest::named_temp_file::named_temp_file): New

View file

@ -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<line_span> tmp_spans (1 + rich_location::MAX_RANGES);
auto_vec<line_span> 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.

View file

@ -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;

View file

@ -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. */

View file

@ -1,3 +1,10 @@
2016-08-30 David Malcolm <dmalcolm@redhat.com>
* 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 <dmalcolm@redhat.com>
* g++.dg/template/double-greater-than-fixit.C: New test case.

View file

@ -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 "" } */
}

View file

@ -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

View file

@ -1,3 +1,42 @@
2016-08-30 David Malcolm <dmalcolm@redhat.com>
* include/line-map.h (class semi_embedded_vec): New class.
(semi_embedded_vec<T, NUM_EMBEDDED>::semi_embedded_vec): New ctor.
(semi_embedded_vec<T, NUM_EMBEDDED>::~semi_embedded_vec): New
dtor.
(semi_embedded_vec<T, NUM_EMBEDDED>::operator[]): New methods.
(semi_embedded_vec<T, NUM_EMBEDDED>::push): New method.
(semi_embedded_vec<T, NUM_EMBEDDED>::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 <dmalcolm@redhat.com>
* include/line-map.h (rich_location::add_fixit_insert): Add

View file

@ -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 <typename T, int NUM_EMBEDDED>
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 <typename T, int NUM_EMBEDDED>
semi_embedded_vec<T, NUM_EMBEDDED>::semi_embedded_vec ()
: m_num (0), m_alloc (0), m_extra (NULL)
{
}
/* semi_embedded_vec's dtor. Release any dynamically-allocated memory. */
template <typename T, int NUM_EMBEDDED>
semi_embedded_vec<T, NUM_EMBEDDED>::~semi_embedded_vec ()
{
XDELETEVEC (m_extra);
}
/* Look up element IDX, mutably. */
template <typename T, int NUM_EMBEDDED>
T&
semi_embedded_vec<T, NUM_EMBEDDED>::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 <typename T, int NUM_EMBEDDED>
const T&
semi_embedded_vec<T, NUM_EMBEDDED>::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 <typename T, int NUM_EMBEDDED>
void
semi_embedded_vec<T, NUM_EMBEDDED>::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 <typename T, int NUM_EMBEDDED>
void
semi_embedded_vec<T, NUM_EMBEDDED>::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 <location_range, STATICALLY_ALLOCATED_RANGES> 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 <fixit_hint *, MAX_STATIC_FIXIT_HINTS> m_fixit_hints;
bool m_seen_impossible_fixit;
};

View file

@ -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);
linemap_assert (idx <= m_ranges.count ());
location_range *locrange = &m_ranges[idx];
locrange->m_loc = loc;
locrange->m_show_caret_p = show_caret_p;
/* 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,