aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2019-02-20 20:07:20 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2019-02-20 20:07:20 +0000
commit200a8e1a38d11c112a460e026663e8301b201d85 (patch)
tree95cf9e2472514f059dbf50ec176a47c6b017d7ca /gcc
parentb054705ae6b841b297e621ac20e9023a671d33bd (diff)
downloadgcc-200a8e1a38d11c112a460e026663e8301b201d85.zip
gcc-200a8e1a38d11c112a460e026663e8301b201d85.tar.gz
gcc-200a8e1a38d11c112a460e026663e8301b201d85.tar.bz2
Fix ICE with #line directive (PR c/89410)
PR c/89410 reports various issues with #line directives with very large numbers; one of them is an ICE inside diagnostic-show-locus.c when emitting a diagnostic at line 0xffffffff. The issue is that the arithmetic in layout::calculate_line_spans to determine if two line spans are sufficiently close to consolidate was using the unsigned 32-bit linenum_type, which was overflowing when comparing the line for the expanded location with those of the location range (all on line 0xffffffff), leading to it erroneously adding two spans for the same line, leading to an assertion failure. This patch fixes the ICE by generalizing the use of long long in line-map.h's comparison function for linenum_type into a new linenum_arith_t typedef, and using it here. Doing so uncovered a second problem: the loop to print the lines within the line_span for this case is infinite: looping from 0xfffffff upwards, overflowing to 0, and then never becoming greater than 0xfffffff. The patch fixes this by using linenum_arith_t there also. gcc/ChangeLog: PR c/89410 * diagnostic-show-locus.c (layout::calculate_line_spans): Use linenum_arith_t when determining if two adjacent line spans are close enough to merge. (diagnostic_show_locus): Use linenum_arith_t when iterating over lines within each line_span. gcc/testsuite/ChangeLog: PR c/89410 * gcc.dg/pr89410-1.c: New test. * gcc.dg/pr89410-2.c: New test. libcpp/ChangeLog: PR c/89410 * include/line-map.h (linenum_arith_t): New typedef. (compare): Use it. From-SVN: r269050
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/diagnostic-show-locus.c9
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/pr89410-1.c9
-rw-r--r--gcc/testsuite/gcc.dg/pr89410-2.c13
5 files changed, 43 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 13580de..75ff134 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2019-02-20 David Malcolm <dmalcolm@redhat.com>
+
+ PR c/89410
+ * diagnostic-show-locus.c (layout::calculate_line_spans): Use
+ linenum_arith_t when determining if two adjacent line spans are
+ close enough to merge.
+ (diagnostic_show_locus): Use linenum_arith_t when iterating over
+ lines within each line_span.
+
2019-02-20 Andre Vieira <andre.simoesdiasvieira@arm.com>
PR target/86487
diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c
index ddc9421..205ee56 100644
--- a/gcc/diagnostic-show-locus.c
+++ b/gcc/diagnostic-show-locus.c
@@ -1211,7 +1211,8 @@ layout::calculate_line_spans ()
const line_span *next = &tmp_spans[i];
gcc_assert (next->m_first_line >= current->m_first_line);
const int merger_distance = m_show_line_numbers_p ? 1 : 0;
- if (next->m_first_line <= current->m_last_line + 1 + merger_distance)
+ if ((linenum_arith_t)next->m_first_line
+ <= (linenum_arith_t)current->m_last_line + 1 + merger_distance)
{
/* We can merge them. */
if (next->m_last_line > current->m_last_line)
@@ -2301,8 +2302,10 @@ diagnostic_show_locus (diagnostic_context * context,
context->start_span (context, exploc);
}
}
- linenum_type last_line = line_span->get_last_line ();
- for (linenum_type row = line_span->get_first_line ();
+ /* Iterate over the lines within this span (using linenum_arith_t to
+ avoid overflow with 0xffffffff causing an infinite loop). */
+ linenum_arith_t last_line = line_span->get_last_line ();
+ for (linenum_arith_t row = line_span->get_first_line ();
row <= last_line; row++)
layout.print_line (row);
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7a407cd..9d344ba 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2019-02-20 David Malcolm <dmalcolm@redhat.com>
+
+ PR c/89410
+ * gcc.dg/pr89410-1.c: New test.
+ * gcc.dg/pr89410-2.c: New test.
+
2019-02-20 Pat Haugen <pthaugen@us.ibm.com>
* lib/target-supports.exp (check_effective_target_vect_usad_char):
diff --git a/gcc/testsuite/gcc.dg/pr89410-1.c b/gcc/testsuite/gcc.dg/pr89410-1.c
new file mode 100644
index 0000000..73dc6d4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr89410-1.c
@@ -0,0 +1,9 @@
+/* { dg-options "" } */
+
+int main(void)
+{
+ /* This is 0xffffffff. */
+#line 4294967295
+#warning msg
+ /* { dg-warning "msg" "" { target *-*-* } -1 } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr89410-2.c b/gcc/testsuite/gcc.dg/pr89410-2.c
new file mode 100644
index 0000000..76e781b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr89410-2.c
@@ -0,0 +1,13 @@
+/* { dg-options "-fdiagnostics-show-caret" } */
+
+int main(void)
+{
+ /* This is 0x7fffffffffffffff, which truncates to 0xffffffff. */
+#line 9223372036854775807 /* { dg-warning "line number out of range" } */
+#warning msg
+ /* { dg-begin-multiline-output "" }
+ #line 9223372036854775807
+ ^~~~~~~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+ /* { dg-warning "msg" "" { target *-*-* } -1 } */
+}