https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118838
Lewis Hyatt <lhyatt at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Last reconfirmed| |2025-02-11 Version|14.2.1 |unknown CC| |lhyatt at gcc dot gnu.org Status|UNCONFIRMED |NEW Ever confirmed|0 |1 --- Comment #1 from Lewis Hyatt <lhyatt at gcc dot gnu.org> --- Thanks, so this one is not actually about macros or the C frontend, you will see the same with C++ and also without the macro (if you put all tokens on the same line). The reason is that -Wunknown-pragmas is issued from the def_pragma() callback: directives.cc: pfile->cb.def_pragma (pfile, pfile->directive_line); and libcpp is passing pfile->directive_line to this callback, which is a location for the line as a whole and not for the specific location of the unknown pragma token. Prior to r15-4505, it wouldn't have worked anyway due to PR114423, but now it would work if pfile->directive_line were replaced by a better location. However, I don't think we can just change it here, affecting other uses of the def_pragma callback. (For example, preprocess-only mode in c-ppoutput.cc uses this location, and changing from pfile->directive_line to something like the location of the _Pragma token would change its output, in case say the _Pragma started and ended on different lines.) It seems safer to modify the warning to be issued at a better location; libcpp provides diagnostic_override_loc already to say what location should be used (the _Pragma token), but it needs a new accessor function added in order for the caller to find out what it is. Like this: ==== 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) + fe_loc = loc; space = name = (const unsigned char *) ""; 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. */ +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 ==== I can test this sometime, some existing -Wunknown-pragmas tests will need to be tweaked for the improved locations. Given this has never worked in any version of GCC, it will probably need to wait for GCC 16 at this point.