From 65c1cb358999e9d1618834af341b31837ede839e Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 4 Feb 2021 15:20:59 -0500 Subject: [PATCH] diagnostics: fix excessive range-printing involving macros [PR97932] 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. 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 --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 "" } */ + -- 2.30.2