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:
committed by
David Malcolm
parent
fb8e9c5e8e
commit
b816477a5a
+132
-13
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user