@@ -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);
}
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-options "" } */
+
+int main(void)
+{
+ /* This is 0xffffffff. */
+#line 4294967295
+#warning msg
+ /* { dg-warning "msg" "" { target *-*-* } -1 } */
+}
new file mode 100644
@@ -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 } */
+}
@@ -49,13 +49,16 @@ along with this program; see the file COPYING3. If not see
/* The type of line numbers. */
typedef unsigned int linenum_type;
+/* A type for doing arithmetic on line numbers. */
+typedef long long linenum_arith_t;
+
/* A function for for use by qsort for comparing line numbers. */
inline int compare (linenum_type lhs, linenum_type rhs)
{
- /* Avoid truncation issues by using long long for the comparison,
+ /* Avoid truncation issues by using linenum_arith_t for the comparison,
and only consider the sign of the result. */
- long long diff = (long long)lhs - (long long)rhs;
+ linenum_arith_t diff = (linenum_arith_t)lhs - (linenum_arith_t)rhs;
if (diff)
return diff > 0 ? 1 : -1;
return 0;