diff options
author | David Malcolm <dmalcolm@redhat.com> | 2017-01-07 21:33:59 +0000 |
---|---|---|
committer | David Malcolm <dmalcolm@gcc.gnu.org> | 2017-01-07 21:33:59 +0000 |
commit | 5ccf1d8d1073544f3d3c24e2168fc12e983dfa47 (patch) | |
tree | d50cf2a1d95d451c655a244f774cbcdbb459d9df /libcpp/line-map.c | |
parent | ff98fa955b5dc98bb05e30ed79299155d2a2f97c (diff) | |
download | gcc-5ccf1d8d1073544f3d3c24e2168fc12e983dfa47.zip gcc-5ccf1d8d1073544f3d3c24e2168fc12e983dfa47.tar.gz gcc-5ccf1d8d1073544f3d3c24e2168fc12e983dfa47.tar.bz2 |
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
Diffstat (limited to 'libcpp/line-map.c')
-rw-r--r-- | libcpp/line-map.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/libcpp/line-map.c b/libcpp/line-map.c index 77beaff..b410c00 100644 --- a/libcpp/line-map.c +++ b/libcpp/line-map.c @@ -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 *> |