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:
parent
fb8e9c5e8e
commit
b816477a5a
10 changed files with 405 additions and 61 deletions
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 "" } */
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue