From d6dd1b60846e1589ce31dce3435f8b8fea556d3d Mon Sep 17 00:00:00 2001 From: dmalcolm Date: Wed, 31 Aug 2016 00:35:01 +0000 Subject: 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 . 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::semi_embedded_vec): New ctor. (semi_embedded_vec::~semi_embedded_vec): New dtor. (semi_embedded_vec::operator[]): New methods. (semi_embedded_vec::push): New method. (semi_embedded_vec::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 --- libcpp/ChangeLog | 39 +++++++++++++ libcpp/include/line-map.h | 145 +++++++++++++++++++++++++++++++++++++++++----- libcpp/line-map.c | 92 ++++++++++++++++------------- 3 files changed, 224 insertions(+), 52 deletions(-) (limited to 'libcpp') diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index a753033b8261..595d6ca4cca8 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,42 @@ +2016-08-30 David Malcolm + + * include/line-map.h (class semi_embedded_vec): New class. + (semi_embedded_vec::semi_embedded_vec): New ctor. + (semi_embedded_vec::~semi_embedded_vec): New + dtor. + (semi_embedded_vec::operator[]): New methods. + (semi_embedded_vec::push): New method. + (semi_embedded_vec::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 * include/line-map.h (rich_location::add_fixit_insert): Add 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 +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 +semi_embedded_vec::semi_embedded_vec () +: m_num (0), m_alloc (0), m_extra (NULL) +{ +} + +/* semi_embedded_vec's dtor. Release any dynamically-allocated memory. */ + +template +semi_embedded_vec::~semi_embedded_vec () +{ + XDELETEVEC (m_extra); +} + +/* Look up element IDX, mutably. */ + +template +T& +semi_embedded_vec::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 +const T& +semi_embedded_vec::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 +void +semi_embedded_vec::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 +void +semi_embedded_vec::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 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 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, -- cgit v1.2.3