From 620cd7861e1266991c9c2a82e1e2d5f4d723ec88 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 27 Apr 2021 17:13:39 -0400 Subject: [PATCH] c++: -Wdeprecated-copy and #pragma diagnostic [PR94492] -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 | 8 ++-- gcc/diagnostic.c | 85 ++++++++++++++++++++++----------- gcc/diagnostic.h | 2 + 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/cp/decl2.c b/gcc/cp/decl2.c index 89f874a..e46fded 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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); diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 246d752..d58586f 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 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); diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 9a6eefc..1b9d6b1 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_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 index 0000000..42852a7 --- /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; +} -- 2.7.4