Fix linemap corruption after very wide source lines (PR c++/72803)
PR c++/72803 describes an issue where a fix-it hint is to be emitted at column 512 of a 511-column source line, leading to an ICE. The root cause is a bug in linemap_line_start, when transitioning from lines >= 512 in width to narrow lines. The wide line in the reproducer has a line map with: m_column_and_range_bits = 15, m_range_bits = 5 giving 10 effective bits for representing columns, so that columns <= 1023 can be represented. When parsing the following line, linemap_line_start (..., ..., max_column_hint=0); is called. This leads to the "add_map" logic, due to this condition: || (max_column_hint <= 80 && effective_column_bits >= 10) i.e. the new line is sufficiently narrower than the old one to potentially use a new linemap (so as to conserve values within the location_t space). It then attempts to avoid allocating a new line map. Part of the logic to determine if we really need a new line map is this condition: SOURCE_COLUMN (map, highest) >= (1U << column_bits) The above condition is incorrect: we need to determine if the highest column we've handed out will fit within the proposed *effective* column bits, but "column_bits" here is the column plus the range bits, rather than just the column bits. Hence in this case linemap_line_start erroneously decides that we don't need a new line map, and updates the column bits within the existing line map, so any location_t values we've already handed out within it that are offset from the start by >= (1<<new_column_and_range_bits) effectively change meaning, leading to incorrect line&column information when decoding them, and various "interesting" ways for the linemap code to fail. The fix is to use the effective column bits in the above conditional. gcc/ChangeLog: PR c++/72803 * input.c (selftest::test_accessing_ordinary_linemaps): Verify that the transition from a max line width >= 1<<10 to narrower lines works correctly. gcc/testsuite/ChangeLog: PR c++/72803 * g++.dg/diagnostic/pr72803.C: New test case. libcpp/ChangeLog: PR c++/72803 * line-map.c (linemap_line_start): When determining if the highest column given out so far will fit into a proposed change to the current map, use the effective number of column bits, rather than the total number of column + range bits. From-SVN: r244199
This commit is contained in:
parent
ff98fa955b
commit
5ccf1d8d10
6 changed files with 42 additions and 1 deletions
|
@ -1,3 +1,10 @@
|
|||
2017-01-07 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR c++/72803
|
||||
* input.c (selftest::test_accessing_ordinary_linemaps): Verify
|
||||
that the transition from a max line width >= 1<<10 to narrower
|
||||
lines works correctly.
|
||||
|
||||
2017-01-07 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
* doc/options.texi (PerFunction): New.
|
||||
|
|
12
gcc/input.c
12
gcc/input.c
|
@ -1688,6 +1688,17 @@ test_accessing_ordinary_linemaps (const line_table_case &case_)
|
|||
linemap_line_start (line_table, 3, 2000);
|
||||
location_t loc_e = linemap_position_for_column (line_table, 700);
|
||||
|
||||
/* Transitioning back to a short line. */
|
||||
linemap_line_start (line_table, 4, 0);
|
||||
location_t loc_back_to_short = linemap_position_for_column (line_table, 100);
|
||||
|
||||
if (should_have_column_data_p (loc_back_to_short))
|
||||
{
|
||||
/* Verify that we switched to short lines in the linemap. */
|
||||
line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
|
||||
ASSERT_EQ (7, map->m_column_and_range_bits - map->m_range_bits);
|
||||
}
|
||||
|
||||
linemap_add (line_table, LC_LEAVE, false, NULL, 0);
|
||||
|
||||
/* Multiple files. */
|
||||
|
@ -1702,6 +1713,7 @@ test_accessing_ordinary_linemaps (const line_table_case &case_)
|
|||
assert_loceq ("foo.c", 2, 1, loc_c);
|
||||
assert_loceq ("foo.c", 2, 17, loc_d);
|
||||
assert_loceq ("foo.c", 3, 700, loc_e);
|
||||
assert_loceq ("foo.c", 4, 100, loc_back_to_short);
|
||||
assert_loceq ("bar.c", 1, 150, loc_f);
|
||||
|
||||
ASSERT_FALSE (is_location_from_builtin_token (loc_a));
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2017-01-07 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR c++/72803
|
||||
* g++.dg/diagnostic/pr72803.C: New test case.
|
||||
|
||||
2017-01-07 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
* gcc.dg/attr-alloc_size-3.c: Remove regex made redundant by r243461.
|
||||
|
|
9
gcc/testsuite/g++.dg/diagnostic/pr72803.C
Normal file
9
gcc/testsuite/g++.dg/diagnostic/pr72803.C
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* Long line, with a close brace at column 511, hence with the insertion
|
||||
point for the missing semicolon at column 512. */
|
||||
class test { }
|
||||
# 1 "" 1
|
||||
// The line directive appears to be necessary to trigger the ICE
|
||||
// { dg-error "style of line directive is a GCC extension" "" { target *-*-* } .-2 }
|
||||
|
||||
/* Verify that we get the correct line and column for the diagnostic. */
|
||||
// { dg-error "512: expected .;. after class definition" "" { target *-*-* } 3 }
|
|
@ -1,3 +1,11 @@
|
|||
2017-01-07 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR c++/72803
|
||||
* line-map.c (linemap_line_start): When determining if the highest
|
||||
column given out so far will fit into a proposed change to the
|
||||
current map, use the effective number of column bits, rather than
|
||||
the total number of column + range bits.
|
||||
|
||||
2017-01-01 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
Update copyright years.
|
||||
|
|
|
@ -752,7 +752,7 @@ linemap_line_start (struct line_maps *set, linenum_type to_line,
|
|||
single line we can sometimes just increase its column_bits instead. */
|
||||
if (line_delta < 0
|
||||
|| last_line != ORDINARY_MAP_STARTING_LINE_NUMBER (map)
|
||||
|| SOURCE_COLUMN (map, highest) >= (1U << column_bits)
|
||||
|| SOURCE_COLUMN (map, highest) >= (1U << (column_bits - range_bits))
|
||||
|| range_bits < map->m_range_bits)
|
||||
map = linemap_check_ordinary
|
||||
(const_cast <line_map *>
|
||||
|
|
Loading…
Add table
Reference in a new issue