From 79cf599406a6a51e2fdd47810fdba89e04cbf1cc Mon Sep 17 00:00:00 2001 From: DJ Delorie Date: Wed, 18 Jan 2006 15:02:42 -0500 Subject: [PATCH] c-pragma.c (handle_pragma_diagnostic): New. * c-pragma.c (handle_pragma_diagnostic): New. (init_pragma): Register it. * doc/extend.texi: Document it. * diagnostic.def: Add DK_UNSPECIFIED and DK_IGNORED. * diagnostic.h (diagnostic_classify_diagnostic): Declare. (diagnostic_context): Add classify_diagnostic[]. * diagnostic.c (diagnostic_count_diagnostic): Don't count warnings as errors if they're overridden to DK_WARNING. (diagnostic_initialize): Initialize classify_diagnostic[]. (diagnostic_set_kind_override): New. (diagnostic_report_diagnostic): Check for kind changes. * opts.c (common_handle_option): Take lang_mask. Update callers. Handle OPT_Werror_. * common.opt (Werror=): New. * doc/invoke.texi: Document -Werror=* From-SVN: r109907 --- gcc/ChangeLog | 21 ++++++++++++++++- gcc/c-pragma.c | 56 ++++++++++++++++++++++++++++++++++++++++++--- gcc/common.opt | 6 ++++- gcc/diagnostic.c | 50 ++++++++++++++++++++++++++++++++++++---- gcc/diagnostic.def | 14 ++++++++++++ gcc/diagnostic.h | 14 +++++++++++- gcc/doc/extend.texi | 48 +++++++++++++++++++++++++++++++++++++- gcc/doc/invoke.texi | 20 ++++++++++++++-- gcc/opts.c | 36 +++++++++++++++++++++++++---- 9 files changed, 247 insertions(+), 18 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d6c62f61536..cd3a907bda6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2006-01-18 DJ Delorie + + * c-pragma.c (handle_pragma_diagnostic): New. + (init_pragma): Register it. + * doc/extend.texi: Document it. + + * diagnostic.def: Add DK_UNSPECIFIED and DK_IGNORED. + * diagnostic.h (diagnostic_classify_diagnostic): Declare. + (diagnostic_context): Add classify_diagnostic[]. + * diagnostic.c (diagnostic_count_diagnostic): Don't count warnings + as errors if they're overridden to DK_WARNING. + (diagnostic_initialize): Initialize classify_diagnostic[]. + (diagnostic_set_kind_override): New. + (diagnostic_report_diagnostic): Check for kind changes. + * opts.c (common_handle_option): Take lang_mask. Update callers. + Handle OPT_Werror_. + * common.opt (Werror=): New. + * doc/invoke.texi: Document -Werror=* + 2006-01-18 Jeff Law * tree-vrp.c (test_for_singularity): Correct test for new @@ -640,7 +659,7 @@ * basic-block.h: Remove the prototype for partition_hot_cold_basic_blocks. -2006-01-16 Rafael Ćvila de EspĆ­ndola +2006-01-16 Rafael Ćvila de EspĆ­ndola * cppspec.c (lang_specific_spec_functions): remove * gcc.c (lookup_spec_function): use static_spec_functions directelly diff --git a/gcc/c-pragma.c b/gcc/c-pragma.c index 554e57f932b..5256758d94b 100644 --- a/gcc/c-pragma.c +++ b/gcc/c-pragma.c @@ -1,6 +1,6 @@ /* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack. - Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 - Free Software Foundation, Inc. + Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + 2006 Free Software Foundation, Inc. This file is part of GCC. @@ -36,7 +36,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "tm_p.h" #include "vec.h" #include "target.h" - +#include "diagnostic.h" +#include "opts.h" #define GCC_BAD(gmsgid) \ do { warning (OPT_Wpragmas, gmsgid); return; } while (0) @@ -668,6 +669,53 @@ handle_pragma_visibility (cpp_reader *dummy ATTRIBUTE_UNUSED) #endif +static void +handle_pragma_diagnostic(cpp_reader *ARG_UNUSED(dummy)) +{ + const char *kind_string, *option_string; + unsigned int option_index; + enum cpp_ttype token; + diagnostic_t kind; + tree x; + + if (cfun) + { + error ("#pragma GCC diagnostic not allowed inside functions"); + return; + } + + token = pragma_lex (&x); + if (token != CPP_NAME) + GCC_BAD ("missing [error|warning|ignored] after %<#pragma GCC diagnostic%>"); + kind_string = IDENTIFIER_POINTER (x); + if (strcmp (kind_string, "error") == 0) + kind = DK_ERROR; + else if (strcmp (kind_string, "warning") == 0) + kind = DK_WARNING; + else if (strcmp (kind_string, "ignored") == 0) + kind = DK_IGNORED; + else + GCC_BAD ("expected [error|warning|ignored] after %<#pragma GCC diagnostic%>"); + + token = pragma_lex (&x); + if (token != CPP_STRING) + GCC_BAD ("missing option after %<#pragma GCC diagnostic%> kind"); + option_string = TREE_STRING_POINTER (x); + for (option_index = 0; option_index < cl_options_count; option_index++) + if (strcmp (cl_options[option_index].opt_text, option_string) == 0) + { + /* This overrides -Werror, for example. */ + diagnostic_classify_diagnostic (global_dc, option_index, kind); + /* This makes sure the option is enabled, like -Wfoo would do. */ + if (cl_options[option_index].var_type == CLVC_BOOLEAN + && cl_options[option_index].flag_var + && kind != DK_IGNORED) + *(int *) cl_options[option_index].flag_var = 1; + return; + } + GCC_BAD ("unknown option after %<#pragma GCC diagnostic%> kind"); +} + /* A vector of registered pragma callbacks. */ DEF_VEC_O (pragma_handler); @@ -767,6 +815,8 @@ init_pragma (void) c_register_pragma ("GCC", "visibility", handle_pragma_visibility); #endif + c_register_pragma ("GCC", "diagnostic", handle_pragma_diagnostic); + c_register_pragma (0, "redefine_extname", handle_pragma_redefine_extname); c_register_pragma (0, "extern_prefix", handle_pragma_extern_prefix); diff --git a/gcc/common.opt b/gcc/common.opt index 8fe9bee7e9a..d16b9977c93 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1,6 +1,6 @@ ; Options for the language- and target-independent parts of the compiler. -; Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. +; Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. ; ; This file is part of GCC. ; @@ -81,6 +81,10 @@ Werror Common Var(warnings_are_errors) Treat all warnings as errors +Werror= +Common Joined +Treat specified warning as error + Wextra Common Print extra (possibly unwanted) warnings diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 7f4d8147340..48ba2968f3b 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -1,5 +1,5 @@ /* Language-independent diagnostic subroutines for the GNU Compiler Collection - Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Contributed by Gabriel Dos Reis @@ -61,6 +61,7 @@ static void real_abort (void) ATTRIBUTE_NORETURN; /* A diagnostic_context surrogate for stderr. */ static diagnostic_context global_diagnostic_context; diagnostic_context *global_dc = &global_diagnostic_context; + /* Return a malloc'd string containing MSG formatted a la printf. The caller is responsible for freeing the memory. */ @@ -102,6 +103,8 @@ diagnostic_initialize (diagnostic_context *context) memset (context->diagnostic_count, 0, sizeof context->diagnostic_count); context->issue_warnings_are_errors_message = true; context->warning_as_error_requested = false; + memset (context->classify_diagnostic, DK_UNSPECIFIED, + sizeof context->classify_diagnostic); context->show_option_requested = false; context->abort_on_error = false; context->internal_error = NULL; @@ -202,7 +205,12 @@ diagnostic_count_diagnostic (diagnostic_context *context, if (!diagnostic_report_warnings_p ()) return false; - if (!context->warning_as_error_requested) + /* -Werror can reclassify warnings as errors, but + classify_diagnostic can reclassify it back to a warning. The + second part of this test detects that case. */ + if (!context->warning_as_error_requested + || (context->classify_diagnostic[diagnostic->option_index] + == DK_WARNING)) { ++diagnostic_kind_count (context, DK_WARNING); break; @@ -324,6 +332,26 @@ default_diagnostic_finalizer (diagnostic_context *context, pp_destroy_prefix (context->printer); } +/* Interface to specify diagnostic kind overrides. Returns the + previous setting, or DK_UNSPECIFIED if the parameters are out of + range. */ +diagnostic_t +diagnostic_classify_diagnostic (diagnostic_context *context, + int option_index, + diagnostic_t new_kind) +{ + diagnostic_t old_kind; + + if (option_index <= 0 + || option_index >= N_OPTS + || new_kind >= DK_LAST_DIAGNOSTIC_KIND) + return DK_UNSPECIFIED; + + old_kind = context->classify_diagnostic[option_index]; + context->classify_diagnostic[option_index] = new_kind; + return old_kind; +} + /* 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 @@ -345,9 +373,21 @@ diagnostic_report_diagnostic (diagnostic_context *context, error_recursion (context); } - if (diagnostic->option_index - && ! option_enabled (diagnostic->option_index)) - return; + if (diagnostic->option_index) + { + /* This tests if the user provided the appropriate -Wfoo or + -Wno-foo option. */ + if (! option_enabled (diagnostic->option_index)) + return; + /* This tests if the user provided the appropriate -Werror=foo + option. */ + if (context->classify_diagnostic[diagnostic->option_index] != DK_UNSPECIFIED) + diagnostic->kind = context->classify_diagnostic[diagnostic->option_index]; + /* This allows for future extenions, like temporarily disabling + warnings for ranges of source code. */ + if (diagnostic->kind == DK_IGNORED) + return; + } context->lock++; diff --git a/gcc/diagnostic.def b/gcc/diagnostic.def index 6820bb72e9f..bbdba2f1aa2 100644 --- a/gcc/diagnostic.def +++ b/gcc/diagnostic.def @@ -1,3 +1,17 @@ +/* DK_UNSPECIFIED must be first so it has a value of zero. We never + assign this kind to an actual diagnostic, we only use this in + variables that can hold a kind, to mean they have yet to have a + kind specified. I.e. they're uninitialized. Within the diagnostic + machinery, this kind also means "don't change the existing kind", + meaning "no change is specified". */ +DEFINE_DIAGNOSTIC_KIND (DK_UNSPECIFIED, "") + +/* If a diagnostic is set to DK_IGNORED, it won't get reported at all. + This is used by the diagnostic machinery when it wants to disable a + diagnostic without disabling the option which causes it. */ +DEFINE_DIAGNOSTIC_KIND (DK_IGNORED, "") + +/* The remainder are real diagnostic types. */ DEFINE_DIAGNOSTIC_KIND (DK_FATAL, "fatal error: ") DEFINE_DIAGNOSTIC_KIND (DK_ICE, "internal compiler error: ") DEFINE_DIAGNOSTIC_KIND (DK_ERROR, "error: ") diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 242cf47b42f..51493ea8bab 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -1,5 +1,5 @@ /* Various declarations for language-independent diagnostics subroutines. - Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Contributed by Gabriel Dos Reis @@ -73,6 +73,13 @@ struct diagnostic_context /* True if it has been requested that warnings be treated as errors. */ bool warning_as_error_requested; + /* For each option index that can be passed to warning() et all + (OPT_* from options.h), this array may contain a new kind that + the diagnostic should be changed to before reporting, or + DK_UNSPECIFIED to leave it as the reported kind, or DK_IGNORED to + not report it at all. N_OPTS is from . */ + char classify_diagnostic[N_OPTS]; + /* True if we should print the command line option which controls each diagnostic, if known. */ bool show_option_requested; @@ -179,6 +186,11 @@ extern diagnostic_context *global_dc; extern void diagnostic_initialize (diagnostic_context *); extern void diagnostic_report_current_module (diagnostic_context *); extern void diagnostic_report_current_function (diagnostic_context *); + +/* Force diagnostics controlled by OPTIDX to be kind KIND. */ +extern diagnostic_t diagnostic_classify_diagnostic (diagnostic_context *, + int /* optidx */, + diagnostic_t /* kind */); extern void diagnostic_report_diagnostic (diagnostic_context *, diagnostic_info *); #ifdef ATTRIBUTE_GCC_DIAG diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 0c2f39c1e10..9d5a8f6076f 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -1,5 +1,5 @@ @c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1996, 1998, 1999, 2000, -@c 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +@c 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. @c This is part of the GCC manual. @c For copying conditions, see the file gcc.texi. @@ -9290,6 +9290,7 @@ for further explanation. * Symbol-Renaming Pragmas:: * Structure-Packing Pragmas:: * Weak Pragmas:: +* Diagnostic Pragmas:: @end menu @node ARM Pragmas @@ -9530,6 +9531,51 @@ It is an error if @var{symbol2} is not defined in the current translation unit. @end table +@node Diagnostic Pragmas +@subsection Diagnostic Pragmas + +GCC allows the user to selectively enable or disable certain types of +diagnostics, and change the kind of the diagnostic. For example, a +project's policy might require that all sources compile with +@option{-Werror} but certain files might have exceptions allowing +specific types of warnings. Or, a project might selectively enable +diagnostics and treat them as errors depending on which preprocessor +macros are defined. + +@table @code +@item #pragma GCC diagnostic @var{kind} @var{option} +@cindex pragma, diagnostic + +Modifies the disposition of a diagnostic. Note that not all +diagnostics are modifyiable; at the moment only warnings (normally +controlled by @samp{-W...}) can be controlled, and not all of them. +Use @option{-fdiagnostics-show-option} to determine which diagnostics +are controllable and which option controls them. + +@var{kind} is @samp{error} to treat this diagnostic as an error, +@samp{warning} to treat it like a warning (even if @option{-Werror} is +in effect), or @samp{ignored} if the diagnostic is to be ignored. +@var{option} is a double quoted string which matches the command line +option. + +@example +#pragma GCC diagnostic warning "-Wformat" +#pragma GCC diagnostic error "-Walways-true" +#pragma GCC diagnostic ignored "-Walways-true" +@end example + +Note that these pragmas override any command line options. Also, +while it is syntactically valid to put these pragmas anywhere in your +sources, the only supported location for them is before any data or +functions are defined. Doing otherwise may result in unpredictable +results depending on how the optimizer manages your sources. If the +same option is listed multiple times, the last one specified is the +one that is in effect. This pragma is not intended to be a general +purpose replacement for command line options, but for implementing +strict control over project policies. + +@end table + @node Unnamed Fields @section Unnamed struct/union fields within structs/unions @cindex struct diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 629e4a9f4aa..924c121502e 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1,5 +1,5 @@ @c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -@c 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +@c 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. @c This is part of the GCC manual. @c For copying conditions, see the file gcc.texi. @@ -226,7 +226,7 @@ Objective-C and Objective-C++ Dialects}. -Wc++-compat -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment @gol -Wconversion -Wno-deprecated-declarations @gol -Wdisabled-optimization -Wno-div-by-zero -Wno-endif-labels @gol --Werror -Werror-implicit-function-declaration @gol +-Werror -Werror-* -Werror-implicit-function-declaration @gol -Wfatal-errors -Wfloat-equal -Wformat -Wformat=2 @gol -Wno-format-extra-args -Wformat-nonliteral @gol -Wformat-security -Wformat-y2k @gol @@ -3411,6 +3411,22 @@ This option is only supported for C and Objective-C@. @opindex Werror Make all warnings into errors. +@item -Werror= +@opindex Werror= +Make the specified warning into an errors. The specifier for a +warning is appended, for example @option{-Werror=switch} turns the +warnings controlled by @option{-Wswitch} into errors. This switch +takes a negative form, to be used to negate @option{-Werror} for +specific warnings, for example @option{-Wno-error=switch} makes +@option{-Wswitch} warnings not be errors, even when @option{-Werror} +is in effect. You can use the @option{-fdiagnostics-show-option} +option to have each controllable warning amended with the option which +controls it, to determine what to use with this option. + +Note that specifying @option{-Werror=}@var{foo} automatically implies +@option{-W}@var{foo}. However, @option{-Wno-error=}@var{foo} does not +imply anything. + @item -Wstack-protector @opindex Wstack-protector This option is only active when @option{-fstack-protector} is active. It diff --git a/gcc/opts.c b/gcc/opts.c index e264b4abcc3..36880862f67 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -1,5 +1,5 @@ /* Command line option handling. - Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Contributed by Neil Booth. This file is part of GCC. @@ -102,7 +102,8 @@ const char **in_fnames; unsigned num_in_fnames; static size_t find_opt (const char *, int); -static int common_handle_option (size_t scode, const char *arg, int value); +static int common_handle_option (size_t scode, const char *arg, int value, + unsigned int lang_mask); static void handle_param (const char *); static void set_Wextra (int); static unsigned int handle_option (const char **argv, unsigned int lang_mask); @@ -405,7 +406,7 @@ handle_option (const char **argv, unsigned int lang_mask) result = 0; if (result && (option->flags & CL_COMMON)) - if (common_handle_option (opt_index, arg, value) == 0) + if (common_handle_option (opt_index, arg, value, lang_mask) == 0) result = 0; if (result && (option->flags & CL_TARGET)) @@ -719,7 +720,8 @@ decode_options (unsigned int argc, const char **argv) VALUE assigned to a variable, it happens automatically. */ static int -common_handle_option (size_t scode, const char *arg, int value) +common_handle_option (size_t scode, const char *arg, int value, + unsigned int lang_mask) { enum opt_code code = (enum opt_code) scode; @@ -759,6 +761,32 @@ common_handle_option (size_t scode, const char *arg, int value) set_Wextra (value); break; + case OPT_Werror_: + { + char *new_option; + int option_index; + new_option = (char *) xmalloc (strlen (arg) + 2); + new_option[0] = 'W'; + strcpy (new_option+1, arg); + option_index = find_opt (new_option, lang_mask); + if (option_index == N_OPTS) + { + error("-Werror-%s: No option -%s", arg, new_option); + } + else + { + int kind = value ? DK_ERROR : DK_WARNING; + diagnostic_classify_diagnostic (global_dc, option_index, kind); + + /* -Werror=foo implies -Wfoo. */ + if (cl_options[option_index].var_type == CLVC_BOOLEAN + && cl_options[option_index].flag_var + && kind == DK_ERROR) + *(int *) cl_options[option_index].flag_var = 1; + } + } + break; + case OPT_Wextra: set_Wextra (value); break;