]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: -Wdeprecated-copy and #pragma diagnostic [PR94492]
authorJason Merrill <jason@redhat.com>
Tue, 27 Apr 2021 21:13:39 +0000 (17:13 -0400)
committerJason Merrill <jason@redhat.com>
Tue, 1 Jun 2021 15:35:47 +0000 (11:35 -0400)
-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.

gcc/ChangeLog:

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

gcc/cp/ChangeLog:

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

gcc/testsuite/ChangeLog:

PR c++/94492
* g++.dg/cpp0x/depr-copy4.C: New test.

gcc/cp/decl2.c
gcc/diagnostic.c
gcc/diagnostic.h
gcc/testsuite/g++.dg/cpp0x/depr-copy4.C [new file with mode: 0644]

index 89f874a32cc95f1fe9496481fd603df684951853..e46fded908af833b0013c9fa8764c4038489148e 100644 (file)
@@ -5499,10 +5499,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_at (DECL_SOURCE_LOCATION (decl),
+                             OPT_Wdeprecated_copy))
        {
          auto_diagnostic_group d;
          tree ctx = DECL_CONTEXT (decl);
index 246d75256cf3f43f58394bce8663567bea6014a2..d58586f25265d8c3e4f5b78c5b59c5d66c661732 100644 (file)
@@ -1122,6 +1122,62 @@ print_option_information (diagnostic_context *context,
     }
 }
 
+/* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
+   as appropriate for #pragma GCC diagnostic and -Werror=foo.  */
+
+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_at (location_t loc, int opt)
+{
+  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);
index 9a6eefcf918e2bb250910a2603ac6c1be9f3019b..1b9d6b1f64d685f8006226dcb66a683256dc734e 100644 (file)
@@ -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_at (location_t, int);
+
 #endif /* ! GCC_DIAGNOSTIC_H */
diff --git a/gcc/testsuite/g++.dg/cpp0x/depr-copy4.C b/gcc/testsuite/g++.dg/cpp0x/depr-copy4.C
new file mode 100644 (file)
index 0000000..42852a7
--- /dev/null
@@ -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;
+}