[PATCH 3/3] PR c/68473: sanitize source range-printing within certain macro expansions (v2)
David Malcolm
dmalcolm@redhat.com
Fri Dec 11 18:25:00 GMT 2015
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
More information about the Gcc-patches
mailing list