diff --git a/gcc/testsuite/c-c++-common/cpp/diagnostic-pragma-1.c b/gcc/testsuite/c-c++-common/cpp/diagnostic-pragma-1.c index 9867c94a8dd..6e37294fd2b 100644 --- a/gcc/testsuite/c-c++-common/cpp/diagnostic-pragma-1.c +++ b/gcc/testsuite/c-c++-common/cpp/diagnostic-pragma-1.c @@ -3,9 +3,8 @@ #pragma GCC warning "warn-a" // { dg-warning warn-a } #pragma GCC error "err-b" // { dg-error err-b } -#define CONST1 _Pragma("GCC warning \"warn-c\"") 1 -#define CONST2 _Pragma("GCC error \"err-d\"") 2 - -char a[CONST1]; // { dg-warning warn-c } -char b[CONST2]; // { dg-error err-d } +#define CONST1 _Pragma("GCC warning \"warn-c\"") 1 // { dg-warning warn-c } +#define CONST2 _Pragma("GCC error \"err-d\"") 2 // { dg-error err-d } +char a[CONST1]; // { dg-note "in expansion of macro 'CONST1'" } +char b[CONST2]; // { dg-note "in expansion of macro 'CONST2'" } diff --git a/gcc/testsuite/c-c++-common/cpp/pragma-diagnostic-loc.c b/gcc/testsuite/c-c++-common/cpp/pragma-diagnostic-loc.c new file mode 100644 index 00000000000..4ef40420cdd --- /dev/null +++ b/gcc/testsuite/c-c++-common/cpp/pragma-diagnostic-loc.c @@ -0,0 +1,17 @@ +/* { dg-do preprocess } */ +/* PR preprocessor/114423 */ +/* Check that we now issue diagnostics at the location of the _Pragma + instead of an invalid location. If we someday manage to issue + diagnostics at better locations in the future, this will need + updating. */ +_Pragma("GCC warning \"warning1\"") /* { dg-warning "1:warning1" } */ +#define P _Pragma("GCC warning \"warning2\"") /* { dg-warning "11:warning2" } */ +P /* { dg-note "in expansion of macro" } */ +#define S "GCC warning \"warning3\"" +/**/ _Pragma(S) /* { dg-warning "6:warning3" } */ + +/* This diagnostic uses a different code path (cpp_diagnostic_at() rather + than cpp_error_with_line()). Also make sure that the dg-note location + does not get overridden to the _Pragma location. */ +#pragma GCC poison xyz /* { dg-note "poisoned here" } */ +/* */ _Pragma("xyz") /* { dg-error "7:attempt to use poisoned" } */ diff --git a/gcc/testsuite/g++.dg/pch/operator-1.C b/gcc/testsuite/g++.dg/pch/operator-1.C index 290b5f7ab21..1138a969536 100644 --- a/gcc/testsuite/g++.dg/pch/operator-1.C +++ b/gcc/testsuite/g++.dg/pch/operator-1.C @@ -1,2 +1,8 @@ #include "operator-1.H" -int main(void){ major(0);} /* { dg-warning "Did not Work" } */ +int main(void){ major(0);} /* { dg-note "in expansion of macro 'major'" } */ +/* Line numbers below pertain to the header file. */ +/* { dg-warning "Did not Work" "" { target *-*-* } 1 } */ +/* { dg-note "in expansion of macro '__glibc_macro_warning1'" "" { target *-*-* } 3 } */ +/* { dg-note "in expansion of macro '__glibc_macro_warning'" "" { target *-*-* } 4 } */ +/* { dg-note "in expansion of macro '__SYSMACROS_DM1'" "" { target *-*-* } 6 } */ +/* { dg-note "in expansion of macro '__SYSMACROS_DM'" "" { target *-*-* } 9 } */ diff --git a/libcpp/directives.cc b/libcpp/directives.cc index 9d235fa1b05..5706c28b835 100644 --- a/libcpp/directives.cc +++ b/libcpp/directives.cc @@ -2430,6 +2430,12 @@ destringize_and_run (cpp_reader *pfile, const cpp_string *in, pfile->buffer->file = pfile->buffer->prev->file; pfile->buffer->sysp = pfile->buffer->prev->sysp; + /* See comment below regarding the use of expansion_loc as the location + for all tokens; arrange here that diagnostics issued during lexing + get the same treatment. */ + const auto prev_loc_override = pfile->diagnostic_override_loc; + pfile->diagnostic_override_loc = expansion_loc; + start_directive (pfile); _cpp_clean_line (pfile); save_directive = pfile->directive; @@ -2497,6 +2503,7 @@ destringize_and_run (cpp_reader *pfile, const cpp_string *in, make that applicable to the real buffer too. */ pfile->buffer->prev->sysp = pfile->buffer->sysp; _cpp_pop_buffer (pfile); + pfile->diagnostic_override_loc = prev_loc_override; /* Reset the old macro state before ... */ XDELETE (pfile->context); diff --git a/libcpp/errors.cc b/libcpp/errors.cc index ad45f61913c..b644c36a9a0 100644 --- a/libcpp/errors.cc +++ b/libcpp/errors.cc @@ -60,13 +60,15 @@ cpp_diagnostic_at (cpp_reader * pfile, enum cpp_diagnostic_level level, enum cpp_warning_reason reason, rich_location *richloc, const char *msgid, va_list *ap) { - bool ret; - if (!pfile->cb.diagnostic) abort (); - ret = pfile->cb.diagnostic (pfile, level, reason, richloc, _(msgid), ap); - - return ret; + if (pfile->diagnostic_override_loc && level != CPP_DL_NOTE) + { + rich_location rc2{pfile->line_table, pfile->diagnostic_override_loc}; + rc2.set_escape_on_output (richloc->escape_on_output_p ()); + return pfile->cb.diagnostic (pfile, level, reason, &rc2, _(msgid), ap); + } + return pfile->cb.diagnostic (pfile, level, reason, richloc, _(msgid), ap); } /* Print a diagnostic at the location of the previously lexed token. */ @@ -201,8 +203,14 @@ cpp_diagnostic_with_line (cpp_reader * pfile, enum cpp_diagnostic_level level, if (!pfile->cb.diagnostic) abort (); + /* Don't override note locations, which will likely make the note + more confusing. */ + const bool do_loc_override + = pfile->diagnostic_override_loc && level != CPP_DL_NOTE; + if (do_loc_override) + src_loc = pfile->diagnostic_override_loc; rich_location richloc (pfile->line_table, src_loc); - if (column) + if (column && !do_loc_override) richloc.override_column (column); ret = pfile->cb.diagnostic (pfile, level, reason, &richloc, _(msgid), ap); diff --git a/libcpp/internal.h b/libcpp/internal.h index a658a8c5739..13186c5a5b0 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -616,6 +616,10 @@ struct cpp_reader zero of said file. */ location_t main_loc; + /* If non-zero, override diagnostic locations (other than DK_NOTE + diagnostics) to this one. */ + location_t diagnostic_override_loc; + /* Returns true iff we should warn about UTF-8 bidirectional control characters. */ bool warn_bidi_p () const