diff mbox series

[committed] diagnostics: fix excessive range-printing involving macros [PR97932]

Message ID 20210204202602.1088240-1-dmalcolm@redhat.com
State New
Headers show
Series [committed] diagnostics: fix excessive range-printing involving macros [PR97932] | expand

Commit Message

David Malcolm Feb. 4, 2021, 8:26 p.m. UTC
PR c/97932 describes a bug in which diagnostic_show_locus prints most
of a source file.

The issue is that it prints a range in which the start and end locations
are part of the same macro map, but the start location is for a token in
the definition of the macro, whereas the end location is for a token in
an argument of the macro.

This patch extends compatible_locations_p to require that range-printing
of macro maps requires the location to either be both for the definition
of the macro, or both for the arguments of the macro (not one of each),
fixing the issue.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r11-7105-g65c1cb358999e9d1618834af341b31837ede839e.

gcc/ChangeLog:
	PR c/97932
	* diagnostic-show-locus.c (compatible_locations_p): Require
	locations in the same macro map to be either both from the
	macro definition, or both from the macro arguments.

gcc/testsuite/ChangeLog:
	PR c/97932
	* gcc.dg/pr97932.c: New test.
---
 gcc/diagnostic-show-locus.c    |   9 +++
 gcc/testsuite/gcc.dg/pr97932.c | 125 +++++++++++++++++++++++++++++++++
 2 files changed, 134 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/pr97932.c
diff mbox series

Patch

diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c
index 92a07c2f60a..458830aa2a9 100644
--- a/gcc/diagnostic-show-locus.c
+++ b/gcc/diagnostic-show-locus.c
@@ -905,6 +905,15 @@  compatible_locations_p (location_t loc_a, location_t loc_b)
       /* Are both within the same macro expansion?  */
       if (linemap_macro_expansion_map_p (map_a))
 	{
+	  /* If so, then they're only compatible if either both are
+	     from the macro definition, or both from the macro arguments.  */
+	  bool loc_a_from_defn
+	    = linemap_location_from_macro_definition_p (line_table, loc_a);
+	  bool loc_b_from_defn
+	    = linemap_location_from_macro_definition_p (line_table, loc_b);
+	  if (loc_a_from_defn != loc_b_from_defn)
+	    return false;
+
 	  /* Expand each location towards the spelling location, and
 	     recurse.  */
 	  const line_map_macro *macro_map = linemap_check_macro (map_a);
diff --git a/gcc/testsuite/gcc.dg/pr97932.c b/gcc/testsuite/gcc.dg/pr97932.c
new file mode 100644
index 00000000000..4a0b3041375
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr97932.c
@@ -0,0 +1,125 @@ 
+/* Verify that we don't emit ranges that span both
+   a macro definition location and a macro expansion location.  */
+
+/* { dg-options "-fdiagnostics-show-caret" } */
+
+/* Various cases involving the ranges of the LHS and RHS operands to "-".  */
+
+/* Case 1
+   start token is in macro definition ("&"),
+   end token is in macro invocation ("a" and "b").  */   
+
+#define M1(A, B) &A - &B /* { dg-error "invalid operands" } */
+
+/* Intervening
+   material
+   that
+   ought
+   not
+   to
+   be
+   printed.  */
+
+int test_1 (float a, int b)
+{
+  return M1(a, b); /* { dg-message "in expansion of macro 'M1'" } */
+}
+
+/* { dg-begin-multiline-output "" }
+ #define M1(A, B) &A - &B
+                     ^
+   { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+   return M1(a, b);
+          ^~
+   { dg-end-multiline-output "" } */
+
+/* Case 2:
+   start and end tokens are both in macro invocation ("&", and "a"/"b").  */   
+
+#define M2(A, B) A - B /* { dg-error "invalid operands" } */
+
+/* Intervening
+   material
+   that
+   ought
+   not
+   to
+   be
+   printed.  */
+
+int test_2 (float a, int b)
+{
+  return M2(&a, &b); /* { dg-message "in expansion of macro 'M2'" } */
+}
+
+/* { dg-begin-multiline-output "" }
+ #define M2(A, B) A - B
+                    ^
+   { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+   return M2(&a, &b);
+          ^~
+   { dg-end-multiline-output "" } */
+
+/* Case 3:
+   start token is in macro invocation ("&"),
+   end token is in macro definition ("a").  */   
+
+#define M3(OP) OP a - OP b /* { dg-error "invalid operands" } */
+
+/* Intervening
+   material
+   that
+   ought
+   not
+   to
+   be
+   printed.  */
+
+int test_3 (float a, int b)
+{
+  return M3(&); /* { dg-message "in expansion of macro 'M3'" } */
+}
+
+/* { dg-begin-multiline-output "" }
+ #define M3(OP) OP a - OP b
+                     ^
+   { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+   return M3(&);
+          ^~
+   { dg-end-multiline-output "" } */
+
+
+/* Case 4:
+   start and end tokens are both in macro definition ("&a").  */   
+
+#define M4 &a - &b /* { dg-error "invalid operands" } */
+
+/* Intervening
+   material
+   that
+   ought
+   not
+   to
+   be
+   printed.  */
+
+int test_4 (float a, int b)
+{
+  return M4; /* { dg-message "in expansion of macro 'M4'" } */
+}
+
+/* { dg-begin-multiline-output "" }
+ #define M4 &a - &b
+            ~~ ^ ~~
+            |    |
+            |    int *
+            float *
+   { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+   return M4;
+          ^~
+   { dg-end-multiline-output "" } */
+