summaryrefslogtreecommitdiff
path: root/gcc/selftest.h
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2018-03-14 13:58:13 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2018-03-14 13:58:13 +0000
commit082284da9d8069290a749218b6aebecab0da2868 (patch)
treeaba9b3b0569617b94157dbe4f5adea052917d7e5 /gcc/selftest.h
parent1422855a403391ab2896f774871c5f3748f415dc (diff)
Fix ICE for missing header fix-it hints with overlarge #line directives (PR c/84852)
PR c/84852 reports an ICE inside diagnostic_show_locus when printing a diagnostic for a source file with a #line >= 2^31: #line 7777777777 int foo (void) { return strlen(""); } where we're attempting to print a fix-it hint at the top of the file and underline the "strlen" (two "line spans"). The #line 7777777777 won't fix within the 32-bit linenum_type, and is truncated from 0x1cf977871 to 0xcf977871 i.e. 3482810481 in decimal. Such a #line is reported by -pedantic and -pedantic-errors, but we shouldn't ICE. The ICE is an assertion failure within layout::calculate_line_spans, where the line spans have not been properly sorted. The layout_ranges are stored as int, rather than linenum_type, giving line -812156815 for the error, and line 1 for the fix-it hint. However, line_span uses linenum_type rather than int. line_span::comparator compares these values as int, and hence decides that (linenum_type)3482810481 aka (int)-812156815 is less than line 1. This leads to this assertion failing in layout::calculate_line_spans: 1105 gcc_assert (next->m_first_line >= current->m_first_line); since it isn't the case that 1 >= 3482810481. The underlying problem is the mix of types for storing line numbers: in parts of libcpp and diagnostic-show-locus.c we use linenum_type; in other places (including libcpp's expanded_location) we use int. I looked at using linenum_type throughout, but doing so turned into a large patch, so this patch fixes the ICE in a less invasive way by merely using linenum_type more consistently just within diagnostic-show-locus.c, and fixing line_span::comparator to properly handle line numbers (and line number differences) >= 2^31, by using a new helper function for linenum_type differences, computing the difference using long long, and using the sign of the difference (as the difference might not fit in the "int" return type imposed by qsort). gcc/ChangeLog: PR c/84852 * diagnostic-show-locus.c (class layout_point): Convert m_line from int to linenum_type. (line_span::comparator): Use linenum "compare" function when comparing line numbers. (test_line_span): New function. (layout_range::contains_point): Convert param "row" from int to linenum_type. (layout_range::intersects_line_p): Likewise. (layout::will_show_line_p): Likewise. (layout::print_source_line): Likewise. (layout::should_print_annotation_line_p): Likewise. (layout::print_annotation_line): Likewise. (layout::print_leading_fixits): Likewise. (layout::annotation_line_showed_range_p): Likewise. (struct line_corrections): Likewise for field m_row. (line_corrections::line_corrections): Likewise for param "row". (layout::print_trailing_fixits): Likewise. (layout::get_state_at_point): Likewise. (layout::get_x_bound_for_row): Likewise. (layout::print_line): Likewise. (diagnostic_show_locus): Likewise for locals "last_line" and "row". (selftest::diagnostic_show_locus_c_tests): Call test_line_span. * input.c (selftest::test_linenum_comparisons): New function. (selftest::input_c_tests): Call it. * selftest.c (selftest::test_assertions): Test ASSERT_GT, ASSERT_GT_AT, ASSERT_LT, and ASSERT_LT_AT. * selftest.h (ASSERT_GT): New macro. (ASSERT_GT_AT): New macro. (ASSERT_LT): New macro. (ASSERT_LT_AT): New macro. gcc/testsuite/ChangeLog: PR c/84852 * gcc.dg/fixits-pr84852-1.c: New test. * gcc.dg/fixits-pr84852-2.c: New test. libcpp/ChangeLog: * include/line-map.h (compare): New function on linenum_type. From-SVN: r258526
Diffstat (limited to 'gcc/selftest.h')
-rw-r--r--gcc/selftest.h38
1 files changed, 38 insertions, 0 deletions
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 67d55ebe130..e3117c6bfc4 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -333,6 +333,44 @@ extern int num_passes;
::selftest::fail ((LOC), desc); \
SELFTEST_END_STMT
+/* Evaluate LHS and RHS and compare them with >, calling
+ ::selftest::pass if LHS > RHS,
+ ::selftest::fail otherwise. */
+
+#define ASSERT_GT(LHS, RHS) \
+ ASSERT_GT_AT ((SELFTEST_LOCATION), (LHS), (RHS))
+
+/* Like ASSERT_GT, but treat LOC as the effective location of the
+ selftest. */
+
+#define ASSERT_GT_AT(LOC, LHS, RHS) \
+ SELFTEST_BEGIN_STMT \
+ const char *desc_ = "ASSERT_GT (" #LHS ", " #RHS ")"; \
+ if ((LHS) > (RHS)) \
+ ::selftest::pass ((LOC), desc_); \
+ else \
+ ::selftest::fail ((LOC), desc_); \
+ SELFTEST_END_STMT
+
+/* Evaluate LHS and RHS and compare them with <, calling
+ ::selftest::pass if LHS < RHS,
+ ::selftest::fail otherwise. */
+
+#define ASSERT_LT(LHS, RHS) \
+ ASSERT_LT_AT ((SELFTEST_LOCATION), (LHS), (RHS))
+
+/* Like ASSERT_LT, but treat LOC as the effective location of the
+ selftest. */
+
+#define ASSERT_LT_AT(LOC, LHS, RHS) \
+ SELFTEST_BEGIN_STMT \
+ const char *desc_ = "ASSERT_LT (" #LHS ", " #RHS ")"; \
+ if ((LHS) < (RHS)) \
+ ::selftest::pass ((LOC), desc_); \
+ else \
+ ::selftest::fail ((LOC), desc_); \
+ SELFTEST_END_STMT
+
/* Evaluate EXPECTED and ACTUAL and compare them with strcmp, calling
::selftest::pass if they are equal,
::selftest::fail if they are non-equal. */