summaryrefslogtreecommitdiff
path: root/libcpp
diff options
context:
space:
mode:
authordmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>2016-08-31 00:35:01 +0000
committerdmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>2016-08-31 00:35:01 +0000
commitd6dd1b60846e1589ce31dce3435f8b8fea556d3d (patch)
tree4e3390b81b9f7a7b900db1de9278ee74805abf77 /libcpp
parent5457e1d5ceb4f10e563f2eb0c260295b538b7ff1 (diff)
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@239879 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libcpp')
-rw-r--r--libcpp/ChangeLog39
-rw-r--r--libcpp/include/line-map.h145
-rw-r--r--libcpp/line-map.c92
3 files changed, 224 insertions, 52 deletions
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index a753033b8261..595d6ca4cca8 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,5 +1,44 @@
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
comments. Add overload omitting the source_location param.
(rich_location::add_fixit_remove): Add comments. Add overloads
diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
index 122e4742ed3d..0c95b292599b 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 <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;
};
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index 318932646a9b..72549ba0732d 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,