diff options
author | Lewis Hyatt <lhyatt@gmail.com> | 2024-03-22 12:55:27 -0400 |
---|---|---|
committer | Lewis Hyatt <lhyatt@gcc.gnu.org> | 2024-10-19 19:25:39 -0400 |
commit | 65c5bbe1c92f9c08e99d3a37c136f2ef9804a37f (patch) | |
tree | db81dc45464d28b24ab77dddaf1d8ab1872847c0 /libcpp | |
parent | 7fa9fd47f161d6b8177439ae2b46a2048a5eaa24 (diff) | |
download | gcc-65c5bbe1c92f9c08e99d3a37c136f2ef9804a37f.zip gcc-65c5bbe1c92f9c08e99d3a37c136f2ef9804a37f.tar.gz gcc-65c5bbe1c92f9c08e99d3a37c136f2ef9804a37f.tar.bz2 |
diagnostics: libcpp: Improve locations for _Pragma lexing diagnostics [PR114423]
libcpp is not currently set up to be able to generate valid
locations for tokens lexed from a _Pragma string. Instead, after obtaining
the tokens, it sets their locations all to the location of the _Pragma
operator itself. This makes things like _Pragma("GCC diagnostic") work well
enough, but if any diagnostics are issued during lexing, prior to resetting
the token locations, those diagnostics get issued at the invalid
locations. Fix that up by adding a new field pfile->diagnostic_override_loc
that instructs libcpp to issue diagnostics at the alternate location.
libcpp/ChangeLog:
PR preprocessor/114423
* internal.h (struct cpp_reader): Add DIAGNOSTIC_OVERRIDE_LOC
field.
* directives.cc (destringize_and_run): Set the new field to the
location of the _Pragma operator.
* errors.cc (cpp_diagnostic_at): Support DIAGNOSTIC_OVERRIDE_LOC to
temporarily issue diagnostics at a different location.
(cpp_diagnostic_with_line): Likewise.
gcc/testsuite/ChangeLog:
PR preprocessor/114423
* c-c++-common/cpp/pragma-diagnostic-loc.c: New test.
* c-c++-common/cpp/diagnostic-pragma-1.c: Adjust expected output.
* g++.dg/pch/operator-1.C: Likewise.
Diffstat (limited to 'libcpp')
-rw-r--r-- | libcpp/directives.cc | 7 | ||||
-rw-r--r-- | libcpp/errors.cc | 20 | ||||
-rw-r--r-- | libcpp/internal.h | 4 |
3 files changed, 25 insertions, 6 deletions
diff --git a/libcpp/directives.cc b/libcpp/directives.cc index 9d235fa..5706c28 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 ad45f61..b644c36 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 a658a8c..13186c5 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 |