On Wed, Feb 12, 2025 at 08:27:37PM -0500, Lewis Hyatt wrote:
> Hello-
>
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118838
>
> This patch addresses the issue mentioned in the PR (another instance of
> _Pragma string location issues). bootstrap + regtest all languages on
> aarch64 looks good. Is it OK please for now or for stage 1? Note, it is not
> a regression, since this never worked in C or C++ frontends; but on the
> other hand, r15-4505 for GCC 15 fixed some related issues, so it could be
> nice if this one gets in along with it. Thanks!
>
> -Lewis
>
> -- >8 --
>
> The warning for -Wunknown-pragmas is issued at the location provided by
> libcpp to the def_pragma() callback. This location is
> cpp_reader::directive_line, which is a location for the start of the line
> only; it is also not a valid location in case the unknown pragma was lexed
> from a _Pragma string. These factors make it impossible to suppress
> -Wunknown-pragmas via _Pragma("GCC diagnostic...") directives on the same
> source line, as in the PR and the test case. Address that by issuing the
> warning at a better location returned by cpp_get_diagnostic_override_loc().
> libcpp already maintains this location to handle _Pragma-related diagnostics
> internally; it was needed also to make a publicly accessible version of it.
>
> gcc/c-family/ChangeLog:
>
> PR c/118838
> * c-lex.cc (cb_def_pragma): Call cpp_get_diagnostic_override_loc()
> to get a valid location at which to issue -Wunknown-pragmas, in case
> it was triggered from a _Pragma.
>
> libcpp/ChangeLog:
>
> PR c/118838
> * errors.cc (cpp_get_diagnostic_override_loc): New function.
> * include/cpplib.h (cpp_get_diagnostic_override_loc): Declare.
>
> gcc/testsuite/ChangeLog:
>
> PR c/118838
> * c-c++-common/cpp/pragma-diagnostic-loc-2.c: New test.
> * g++.dg/gomp/macro-4.C: Adjust expected output.
> * gcc.dg/gomp/macro-4.c: Likewise.
> * gcc.dg/cpp/Wunknown-pragmas-1.c: Likewise.
> ---
> libcpp/errors.cc | 10 +++++++++
> libcpp/include/cpplib.h | 5 +++++
> gcc/c-family/c-lex.cc | 7 +++++-
> .../cpp/pragma-diagnostic-loc-2.c | 15 +++++++++++++
> gcc/testsuite/g++.dg/gomp/macro-4.C | 8 +++----
> gcc/testsuite/gcc.dg/cpp/Wunknown-pragmas-1.c | 22 +++++++++++--------
> gcc/testsuite/gcc.dg/gomp/macro-4.c | 8 +++----
> 7 files changed, 57 insertions(+), 18 deletions(-)
> create mode 100644 gcc/testsuite/c-c++-common/cpp/pragma-diagnostic-loc-2.c
>
> diff --git a/libcpp/errors.cc b/libcpp/errors.cc
> index 9621c4b66ea..d9efb6acd30 100644
> --- a/libcpp/errors.cc
> +++ b/libcpp/errors.cc
> @@ -52,6 +52,16 @@ cpp_diagnostic_get_current_location (cpp_reader *pfile)
> }
> }
>
> +/* Sometimes a diagnostic needs to be generated before libcpp has been able
> + to generate a valid location for the current token; in that case, the
> + non-zero location returned by this function is the preferred one to use.
> */
> +
> +location_t
> +cpp_get_diagnostic_override_loc (const cpp_reader *pfile)
> +{
> + return pfile->diagnostic_override_loc;
> +}
> +
> /* Print a diagnostic at the given location. */
>
> ATTRIBUTE_CPP_PPDIAG (5, 0)
> diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
> index 90aa3160ebf..04d4621da3c 100644
> --- a/libcpp/include/cpplib.h
> +++ b/libcpp/include/cpplib.h
> @@ -1168,6 +1168,11 @@ extern const char *cpp_probe_header_unit (cpp_reader
> *, const char *file,
> extern const char *cpp_get_narrow_charset_name (cpp_reader *) ATTRIBUTE_PURE;
> extern const char *cpp_get_wide_charset_name (cpp_reader *) ATTRIBUTE_PURE;
>
> +/* Sometimes a diagnostic needs to be generated before libcpp has been able
> + to generate a valid location for the current token; in that case, the
> + non-zero location returned by this function is the preferred one to use.
> */
I don't love duplicating the comment like this, it's going to get out of sync.
> +extern location_t cpp_get_diagnostic_override_loc (const cpp_reader *);
> +
> /* This function reads the file, but does not start preprocessing. It
> returns the name of the original file; this is the same as the
> input file, except for preprocessed input. This will generate at
> diff --git a/gcc/c-family/c-lex.cc b/gcc/c-family/c-lex.cc
> index e450c9a57f0..df84020de62 100644
> --- a/gcc/c-family/c-lex.cc
> +++ b/gcc/c-family/c-lex.cc
> @@ -248,7 +248,12 @@ cb_def_pragma (cpp_reader *pfile, location_t loc)
> {
> const unsigned char *space, *name;
> const cpp_token *s;
> - location_t fe_loc = loc;
> +
> + /* If we are processing a _Pragma, LOC is not a valid location, but
> libcpp
> + will provide a good location via this function instead. */
> + location_t fe_loc = cpp_get_diagnostic_override_loc (pfile);
> + if (!fe_loc)
I think checking == UNKNOWN_LOCATION is clearer.
> + fe_loc = loc;
>
> space = name = (const unsigned char *) "";
>
> diff --git a/gcc/testsuite/c-c++-common/cpp/pragma-diagnostic-loc-2.c
> b/gcc/testsuite/c-c++-common/cpp/pragma-diagnostic-loc-2.c
> new file mode 100644
> index 00000000000..e7e8cf23759
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/cpp/pragma-diagnostic-loc-2.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-Wunknown-pragmas" } */
> +
> +/* PR 118838 */
Usually this would be the first line and also mention "c/".
But those comments are details. I think the patch is OK for GCC 16.
Thanks,
Marek