]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
diagnostics: libcpp: Improve locations for _Pragma lexing diagnostics [PR114423]
authorLewis Hyatt <lhyatt@gmail.com>
Fri, 22 Mar 2024 16:55:27 +0000 (12:55 -0400)
committerLewis Hyatt <lhyatt@gcc.gnu.org>
Sat, 19 Oct 2024 23:25:39 +0000 (19:25 -0400)
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.

gcc/testsuite/c-c++-common/cpp/diagnostic-pragma-1.c
gcc/testsuite/c-c++-common/cpp/pragma-diagnostic-loc.c [new file with mode: 0644]
gcc/testsuite/g++.dg/pch/operator-1.C
libcpp/directives.cc
libcpp/errors.cc
libcpp/internal.h

index 9867c94a8ddc3683d420146b42c88ca8da923b31..6e37294fd2ba0df53a756193eb2f02b6d2b41269 100644 (file)
@@ -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 (file)
index 0000000..4ef4042
--- /dev/null
@@ -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" } */
index 290b5f7ab21044d226ac59f16e6c0a423baf678c..1138a96953613841dce51465fcfa12a5bdf4de5d 100644 (file)
@@ -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 } */
index 9d235fa1b05768734479bbf7988d4fe6450e9bb3..5706c28b83530ebb425972a9c423eee8d1849509 100644 (file)
@@ -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);
index ad45f61913c313ecd1b8553b6bc9ca4829e2c005..b644c36a9a03521e11af75711618598dab26e65c 100644 (file)
@@ -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);
 
index a658a8c5739c1f1df5e45db13cd09bfe0c785dd9..13186c5a5b048bd1accdef755a852148a0bde50c 100644 (file)
@@ -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