Changes in v2: - add two more testcases, based on additional reproducers reported (one to the PR, another to a dup); now adds 17 PASS results to gcc.sum. - update for delayed expansion of locations within rich_location and the terminology fixes from the other patches in this kit.
As before this patch fixes PR c/68473 by bulletproofing the new diagnostic_show_locus implementation against ranges that finish before they start (which can happen when using the C preprocessor), falling back to simply printing a caret. gcc/ChangeLog: PR c/68473 * diagnostic-show-locus.c (layout::layout): Sanitize the layout against ranges that finish before they start. gcc/testsuite/ChangeLog: PR c/68473 * gcc.dg/plugin/diagnostic-test-expressions-1.c (fminl): New decl. (TEST_EQ): New macro. (test_macro): New function. * gcc.dg/pr68473-2.c: New test case. * gcc.dg/pr68473-3.c: New test case. * gcc.target/i386/pr68473-1.c: New test case. --- gcc/diagnostic-show-locus.c | 24 +++++++++++++++- .../gcc.dg/plugin/diagnostic-test-expressions-1.c | 17 +++++++++++ gcc/testsuite/gcc.dg/pr68473-2.c | 23 +++++++++++++++ gcc/testsuite/gcc.dg/pr68473-3.c | 33 ++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr68473-1.c | 24 ++++++++++++++++ 5 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/pr68473-2.c create mode 100644 gcc/testsuite/gcc.dg/pr68473-3.c create mode 100644 gcc/testsuite/gcc.target/i386/pr68473-1.c diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c index f279019..0bcd333 100644 --- a/gcc/diagnostic-show-locus.c +++ b/gcc/diagnostic-show-locus.c @@ -473,9 +473,31 @@ layout::layout (diagnostic_context * context, if (caret.file != m_exploc.file) continue; + /* Everything is now known to be in the correct source file, + but it may require further sanitization. */ + layout_range ri (&start, &finish, nested_loc->m_show_caret_p, &caret); + + /* If we have a range that finishes before it starts (perhaps + from something built via macro expansion), printing the + range is likely to be nonsensical. Also, attempting to do so + breaks assumptions within the printing code (PR c/68473). */ + if (ri.m_start.m_line > ri.m_finish.m_line) + { + /* Is this the primary location? */ + if (m_layout_ranges.length () == 0) + { + /* We want to print the caret for the primary location, but + we must sanitize away m_start and m_finish. */ + ri.m_start = ri.m_caret; + ri.m_finish = ri.m_caret; + } + else + /* This is a non-primary location; ignore it. */ + continue; + } + /* Passed all the tests; add the location to m_layout_ranges so that it will be printed. */ - layout_range ri (&start, &finish, nested_loc->m_show_caret_p, &caret); m_layout_ranges.safe_push (ri); /* Update m_first_line/m_last_line if necessary. */ diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c index 175b2ea..97426f6 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c @@ -618,3 +618,20 @@ void test_quadratic (double a, double b, double c) { dg-end-multiline-output "" } */ } + +/* Reproducer for PR c/68473. */ + +extern long double fminl (long double __x, long double __y); +#define TEST_EQ(FUNC) FUNC##l(xl,xl) +void test_macro (long double xl) +{ + __emit_expression_range (0, TEST_EQ (fmin) ); /* { dg-warning "range" } */ +/* { dg-begin-multiline-output "" } + __emit_expression_range (0, TEST_EQ (fmin) ); + ^ + { dg-end-multiline-output "" } */ +/* { dg-begin-multiline-output "" } + #define TEST_EQ(FUNC) FUNC##l(xl,xl) + ^~~~ + { dg-end-multiline-output "" } */ +} diff --git a/gcc/testsuite/gcc.dg/pr68473-2.c b/gcc/testsuite/gcc.dg/pr68473-2.c new file mode 100644 index 0000000..5a10f1c --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr68473-2.c @@ -0,0 +1,23 @@ +/* { dg-options "-fdiagnostics-show-caret -Wall" } */ +#define FOO(bar) bar && 42 /* { dg-warning "suggest parentheses" } */ +int param; +int lhs; +int f() { return lhs || FOO(param); } /* { dg-message "in expansion of" } */ + +/* { dg-begin-multiline-output "" } + #define FOO(bar) bar && 42 + ^ + { dg-end-multiline-output "" } */ + +/* { dg-begin-multiline-output "" } + int f() { return lhs || FOO(param); } + ^~~ + { dg-end-multiline-output "" } */ + +/* TODO: ideally we'd print the full range of the expression as it + pertains to the primary caret: + + #define FOO(bar) bar && 42 + ~~~~^~~~~ + +*/ diff --git a/gcc/testsuite/gcc.dg/pr68473-3.c b/gcc/testsuite/gcc.dg/pr68473-3.c new file mode 100644 index 0000000..d1f3107 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr68473-3.c @@ -0,0 +1,33 @@ +/* From PR c/68839 (dup of 68473). */ +/* { dg-options "-fdiagnostics-show-caret -Wduplicated-cond" } */ + +struct S { void *q; }; + +#define NULL (void*)0 + +void f (struct S *p) +{ + if (p->q != NULL) { } /* { dg-message "previously used here" } */ + else if (p->q != NULL) { } /* { dg-warning "duplicated" } */ +} + +/* { dg-begin-multiline-output "" } + else if (p->q != NULL) { } + ^ + { dg-end-multiline-output "" } */ + +/* { dg-begin-multiline-output "" } + if (p->q != NULL) { } + ^ + { dg-end-multiline-output "" } */ + +/* TODO: Ideally we'd print some form of the ranges as they pertain to the + primary caret within the location: + + else if (p->q != NULL) { } + ~~~~~^~~~~~~ + + if (p->q != NULL) { } + ~~~~~^~~~~~~ + +*/ diff --git a/gcc/testsuite/gcc.target/i386/pr68473-1.c b/gcc/testsuite/gcc.target/i386/pr68473-1.c new file mode 100644 index 0000000..ffffaa7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr68473-1.c @@ -0,0 +1,24 @@ +/* { dg-options "-fdiagnostics-show-caret -mno-fp-ret-in-387" } */ + +extern long double fminl (long double __x, long double __y); + +#define TEST_EQ(FUNC) do { \ + if ((long)FUNC##l(xl,xl) != (long)xl) \ + return; \ + } while (0) + +void +foo (long double xl) +{ + TEST_EQ (fmin); /* { dg-error "x87 register return with x87 disabled" } */ +} + +/* { dg-begin-multiline-output "" } + TEST_EQ (fmin); + ^ + { dg-end-multiline-output "" } */ + +/* { dg-begin-multiline-output "" } + if ((long)FUNC##l(xl,xl) != (long)xl) \ + ^~~~ + { dg-end-multiline-output "" } */ -- 1.8.5.3