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
+39
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
+132 -13
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;
};
+53 -39
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,