https://gcc.gnu.org/g:78673484b4055b93207eee0efd60a434b0bf96ab

commit r16-179-g78673484b4055b93207eee0efd60a434b0bf96ab
Author: Lewis Hyatt <lhy...@gmail.com>
Date:   Tue Feb 11 13:45:41 2025 -0500

    c-family: Improve location for -Wunknown-pragmas in a _Pragma [PR118838]
    
    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.

Diff:
---
 gcc/c-family/c-lex.cc                              |  7 ++++++-
 .../c-c++-common/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 ++++----
 libcpp/errors.cc                                   | 10 ++++++++++
 libcpp/include/cpplib.h                            |  2 ++
 7 files changed, 54 insertions(+), 18 deletions(-)

diff --git a/gcc/c-family/c-lex.cc b/gcc/c-family/c-lex.cc
index e450c9a57f0c..fef6ae6f457b 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 == UNKNOWN_LOCATION)
+       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 000000000000..734da2154705
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/pragma-diagnostic-loc-2.c
@@ -0,0 +1,15 @@
+/* PR c/118838 */
+/* { dg-do compile } */
+/* { dg-additional-options "-Wunknown-pragmas" } */
+
+/* Make sure the warnings are suppressed as expected.  */
+
+/* The tokens need to be all on the same line here.  */
+_Pragma ("GCC diagnostic push") _Pragma ("GCC diagnostic ignored 
\"-Wunknown-pragmas\"") _Pragma ("__unknown__") _Pragma ("GCC diagnostic pop")
+
+#define MACRO \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wunknown-pragmas\"") \
+    _Pragma ("__unknown__") \
+    _Pragma ("GCC diagnostic pop")
+MACRO
diff --git a/gcc/testsuite/g++.dg/gomp/macro-4.C 
b/gcc/testsuite/g++.dg/gomp/macro-4.C
index dcc8bcbc8e5c..5aa6d97c6609 100644
--- a/gcc/testsuite/g++.dg/gomp/macro-4.C
+++ b/gcc/testsuite/g++.dg/gomp/macro-4.C
@@ -3,7 +3,7 @@
 // { dg-options "-fopenmp -Wunknown-pragmas" }
 
 #define p              _Pragma ("omp parallel")
-#define omp_p          _Pragma ("omp p")
+#define omp_p          _Pragma ("omp p") // { dg-warning "ignoring '#pragma 
omp _Pragma'" }
 
 void bar (void);
 
@@ -12,18 +12,18 @@ foo (void)
 {
 #pragma omp p          // { dg-warning "-:ignoring '#pragma omp _Pragma'" }
     bar ();
-  omp_p                        // { dg-warning "-:ignoring '#pragma omp 
_Pragma'" }
+    omp_p              // { dg-note "in expansion of macro 'omp_p'" }
     bar ();
 }
 
 #define parallel       serial
-#define omp_parallel   _Pragma ("omp parallel")
+#define omp_parallel   _Pragma ("omp parallel") // { dg-warning "ignoring 
'#pragma omp serial'" }
 
 void
 baz (void)
 {
 #pragma omp parallel   // { dg-warning "-:ignoring '#pragma omp serial'" }
     bar ();
-  omp_parallel         // { dg-warning "-:ignoring '#pragma omp serial'" }
+    omp_parallel        // { dg-note "in expansion of macro 'omp_parallel'" }
     bar ();
 }
diff --git a/gcc/testsuite/gcc.dg/cpp/Wunknown-pragmas-1.c 
b/gcc/testsuite/gcc.dg/cpp/Wunknown-pragmas-1.c
index 06a244e097d3..f3c790195e19 100644
--- a/gcc/testsuite/gcc.dg/cpp/Wunknown-pragmas-1.c
+++ b/gcc/testsuite/gcc.dg/cpp/Wunknown-pragmas-1.c
@@ -8,21 +8,25 @@
 #pragma unknown1 /* { dg-warning "-:unknown1" "unknown1" } */
 
 #define COMMA ,
-#define FOO(x) x
-#define BAR(x) _Pragma("unknown_before") x
-#define BAZ(x) x _Pragma("unknown_after")
+#define FOO(x) x /* { dg-note "in definition of macro 'FOO'" } */
 
-int _Pragma("unknown2") bar1; /* { dg-warning "-:unknown2" "unknown2" } */
+#define BAR1(x) _Pragma("unknown_before1") x  /* { dg-warning 
"unknown_before1" } */
+#define BAR2(x) _Pragma("unknown_before2") x  /* { dg-warning 
"unknown_before2" } */
 
-FOO(int _Pragma("unknown3") bar2); /* { dg-warning "-:unknown3" "unknown3" } */
+#define BAZ1(x) x _Pragma("unknown_after1")  /* { dg-warning "unknown_after1" 
} */
+#define BAZ2(x) x _Pragma("unknown_after2")  /* { dg-warning "unknown_after2" 
} */
 
-int BAR(bar3); /* { dg-warning "-:unknown_before" "unknown_before 1" } */
+int _Pragma("unknown2") bar1; /* { dg-warning "unknown2" "unknown2" } */
 
-BAR(int bar4); /* { dg-warning "-:unknown_before" "unknown_before 2" } */
+FOO(int _Pragma("unknown3") bar2); /* { dg-warning "unknown3" "unknown3" } */
 
-int BAZ(bar5); /* { dg-warning "-:unknown_after" "unknown_after 1" } */
+int BAR1(bar3); /* { dg-note "in expansion of macro 'BAR1'" } */
 
-int BAZ(bar6;) /* { dg-warning "-:unknown_after" "unknown_after 2" } */
+BAR2(int bar4); /* { dg-note "in expansion of macro 'BAR2'" } */
+
+int BAZ1(bar5); /* { dg-note "in expansion of macro 'BAZ1'" } */
+
+int BAZ2(bar6;) /* { dg-note "in expansion of macro 'BAZ2'" } */
 
 FOO(int bar7; _Pragma("unknown4")) /* { dg-warning "-:unknown4" "unknown4" } */
 
diff --git a/gcc/testsuite/gcc.dg/gomp/macro-4.c 
b/gcc/testsuite/gcc.dg/gomp/macro-4.c
index a4ed9a3980af..961c599f2fe7 100644
--- a/gcc/testsuite/gcc.dg/gomp/macro-4.c
+++ b/gcc/testsuite/gcc.dg/gomp/macro-4.c
@@ -3,7 +3,7 @@
 /* { dg-options "-fopenmp -Wunknown-pragmas" } */
 
 #define p              _Pragma ("omp parallel")
-#define omp_p          _Pragma ("omp p")
+#define omp_p          _Pragma ("omp p") /* { dg-warning "ignoring '#pragma 
omp _Pragma'" } */
 
 void bar (void);
 
@@ -12,18 +12,18 @@ foo (void)
 {
 #pragma omp p          /* { dg-warning "-:ignoring '#pragma omp _Pragma'" } */
     bar ();
-  omp_p                        /* { dg-warning "-:ignoring '#pragma omp 
_Pragma'" } */
+  omp_p                        /* { dg-note "in expansion of macro 'omp_p'" } 
*/
     bar ();
 }
 
 #define parallel       serial
-#define omp_parallel   _Pragma ("omp parallel")
+#define omp_parallel   _Pragma ("omp parallel") /* { dg-warning "ignoring 
'#pragma omp serial'" } */
 
 void
 baz (void)
 {
 #pragma omp parallel   /* { dg-warning "-:ignoring '#pragma omp serial'" } */
     bar ();
-  omp_parallel         /* { dg-warning "-:ignoring '#pragma omp serial'" } */
+    omp_parallel        /* { dg-note "in expansion of macro 'omp_parallel'" } 
*/
     bar ();
 }
diff --git a/libcpp/errors.cc b/libcpp/errors.cc
index 9621c4b66ea0..d9efb6acd306 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 3bf33ab48842..7c147ae58477 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -1169,6 +1169,8 @@ 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;
 
+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

Reply via email to