On 5/13/21 1:28 PM, Jason Merrill via Gcc-patches wrote:
Ping.

On 4/28/21 9:32 AM, Jason Merrill wrote:
  -Wdeprecated-copy was depending only on the state of the warning at the
point where we call the function, making it hard to use #pragma diagnostic
to suppress the warning for a particular implicitly declared function.

But checking whether the warning is enabled at the location of the implicit
declaration turned out to be a bit complicated; option_enabled only tests
whether it was enabled at the start of compilation, the actual test only
existed in the middle of diagnostic_report_diagnostic.  So this patch
factors it out and adds a new warning_enabled function to diagnostic.h.

There is a bit of overlap in this patch with my work here:
  https://gcc.gnu.org/pipermail/gcc-patches/2021-January/563862.html
but nothing that concerns me, for whatever it's worth.

In my ongoing work to extend TREE_NO_WARNING to more than one bit
I've been thinking of introducing a function (actually a pair of
them) similar to warning_enabled().  The overloads will take
a tree and gimple* rather than a location so that they can consider
the inlining context.  This is only useful in the middle end so
front ends can still use location_t.

Just one suggestion: since warning_at() takes location_t and int
for the option in that order, I would recommend doing the same
for warning_enabled(), just to reduce the risk of confusion.
(It would be nice if location_t could be something other than
an arithmetic type).

Martin


Tested x86_64-pc-linux-gnu, OK for trunk?

gcc/ChangeLog:

    PR c++/94492
    * diagnostic.h (warning_enabled): Declare.
    * diagnostic.c (diagnostic_enabled): Factor out from...
    (diagnostic_report_diagnostic): ...here.
    (warning_enabled): New.

gcc/cp/ChangeLog:

    PR c++/94492
    * decl2.c (cp_warn_deprecated_use): Check warning_enabled.

gcc/testsuite/ChangeLog:

    PR c++/94492
    * g++.dg/cpp0x/depr-copy4.C: New test.
---
  gcc/diagnostic.h                        |  2 +
  gcc/cp/decl2.c                          |  8 +--
  gcc/diagnostic.c                        | 85 +++++++++++++++++--------
  gcc/testsuite/g++.dg/cpp0x/depr-copy4.C | 16 +++++
  4 files changed, 80 insertions(+), 31 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/depr-copy4.C

diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 9a6eefcf918..caa97da2df9 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -515,4 +515,6 @@ extern int num_digits (int);
  extern json::value *json_from_expanded_location (diagnostic_context *context,
                           location_t loc);
+extern bool warning_enabled (int, location_t = input_location);
+
  #endif /* ! GCC_DIAGNOSTIC_H */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index a82960fb39c..03b7a68aba2 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -5495,10 +5495,10 @@ cp_warn_deprecated_use (tree decl, tsubst_flags_t complain)
        && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
        && copy_fn_p (decl))
      {
-      if (warn_deprecated_copy
-      /* Don't warn about system library classes (c++/86342).  */
-      && (!DECL_IN_SYSTEM_HEADER (decl)
-          || global_dc->dc_warn_system_headers))
+      /* Don't warn if the flag was disabled around the class definition
+     (c++/94492).  */
+      if (warning_enabled (OPT_Wdeprecated_copy,
+               DECL_SOURCE_LOCATION (decl)))
      {
        auto_diagnostic_group d;
        tree ctx = DECL_CONTEXT (decl);
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 246d75256cf..278ec8b706f 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -1122,6 +1122,62 @@ print_option_information (diagnostic_context *context,
      }
  }
+/* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
+   as appropriate.  */
+
+static bool
+diagnostic_enabled (diagnostic_context *context,
+            diagnostic_info *diagnostic)
+{
+  /* Diagnostics with no option or -fpermissive are always enabled.  */
+  if (!diagnostic->option_index
+      || diagnostic->option_index == permissive_error_option (context))
+    return true;
+
+  /* This tests if the user provided the appropriate -Wfoo or
+     -Wno-foo option.  */
+  if (! context->option_enabled (diagnostic->option_index,
+                 context->lang_mask,
+                 context->option_state))
+    return false;
+
+  /* This tests for #pragma diagnostic changes.  */
+  diagnostic_t diag_class
+    = update_effective_level_from_pragmas (context, diagnostic);
+
+  /* This tests if the user provided the appropriate -Werror=foo
+     option.  */
+  if (diag_class == DK_UNSPECIFIED
+      && (context->classify_diagnostic[diagnostic->option_index]
+      != DK_UNSPECIFIED))
+    diagnostic->kind
+      = context->classify_diagnostic[diagnostic->option_index];
+
+  /* This allows for future extensions, like temporarily disabling
+     warnings for ranges of source code.  */
+  if (diagnostic->kind == DK_IGNORED)
+    return false;
+
+  return true;
+}
+
+/* Returns whether warning OPT is enabled at LOC.  */
+
+bool
+warning_enabled (int opt, location_t loc)
+{
+  if (!diagnostic_report_warnings_p (global_dc, loc))
+    return false;
+
+  rich_location richloc (line_table, loc);
+  diagnostic_info diagnostic = {};
+  diagnostic.option_index = opt;
+  diagnostic.richloc = &richloc;
+  diagnostic.message.m_richloc = &richloc;
+  diagnostic.kind = DK_WARNING;
+  return diagnostic_enabled (global_dc, &diagnostic);
+}
+
  /* Report a diagnostic message (an error or a warning) as specified by
     DC.  This function is *the* subroutine in terms of which front-ends
     should implement their specific diagnostic handling modules.  The
@@ -1172,33 +1228,8 @@ diagnostic_report_diagnostic (diagnostic_context *context,
        && diagnostic->kind == DK_WARNING)
      diagnostic->kind = DK_ERROR;
-  if (diagnostic->option_index
-      && diagnostic->option_index != permissive_error_option (context))
-    {
-      /* This tests if the user provided the appropriate -Wfoo or
-     -Wno-foo option.  */
-      if (! context->option_enabled (diagnostic->option_index,
-                     context->lang_mask,
-                     context->option_state))
-    return false;
-
-      /* This tests for #pragma diagnostic changes.  */
-      diagnostic_t diag_class
-    = update_effective_level_from_pragmas (context, diagnostic);
-
-      /* This tests if the user provided the appropriate -Werror=foo
-     option.  */
-      if (diag_class == DK_UNSPECIFIED
-      && (context->classify_diagnostic[diagnostic->option_index]
-          != DK_UNSPECIFIED))
-    diagnostic->kind
-      = context->classify_diagnostic[diagnostic->option_index];
-
-      /* This allows for future extensions, like temporarily disabling
-     warnings for ranges of source code.  */
-      if (diagnostic->kind == DK_IGNORED)
-    return false;
-    }
+  if (!diagnostic_enabled (context, diagnostic))
+    return false;
    if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
      diagnostic_check_max_errors (context);
diff --git a/gcc/testsuite/g++.dg/cpp0x/depr-copy4.C b/gcc/testsuite/g++.dg/cpp0x/depr-copy4.C
new file mode 100644
index 00000000000..42852a70558
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/depr-copy4.C
@@ -0,0 +1,16 @@
+// PR c++/94492
+// { dg-additional-options -Wdeprecated-copy }
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-copy"
+struct expr
+{
+    int a, b;
+    expr& operator=(const expr&) { return *this; }
+};
+#pragma GCC diagnostic pop
+
+expr foo(expr e)
+{
+    return e;
+}

base-commit: f9d670128f6e6b3631a2db575ddf6f19fa43afdc



Reply via email to