-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. 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 -- 2.27.0