Hi! As mentioned in the PR, -Wformat -Werror=format-security -Wformat surprisingly means -Wno-format-security in the end (same effect e.g. with -Wall at the end), while -Wformat -Wformat-security -Wformat (or -Wall) is -Wformat-security.
The problem is that all the EnabledBy and LangEnabledBy options are changed by the related options only if not explicitly set by the user, and for explicit setting by user we mean only those options themselves, not some other option that includes it. In most cases I think that is just fine, say for -Wformat -Wformat=2 -Wformat nobody should expect -Wformat-security to be on. But I think -Werror= should, -pedantic-errors and -Werror-implicit-function-declaration should be an exception, if one uses -Werror=foobar, we should consider -Wfoobar to be set explicitly, similarly for -pedantic-errors we should consider -Wpedantic to be set explicitly and for -Werror-implicit-function-declaration -Wimplicit-function-declaration to be set explicitly. So the following patch implements that, pretty much ensures that control_warning_option when it calls handle_generated_option -> handle_option it will still set_option even in opts_set, not just opts. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2017-02-24 Jakub Jelinek <ja...@redhat.com> PR c/79677 * opts.h (handle_generated_option): Add GENERATED_P argument. * opts-common.c (handle_option): Adjust function comment. (handle_generated_option): Add GENERATED_P argument, pass it to handle_option. (control_warning_option): Pass false to handle_generated_option GENERATED_P. * opts.c (maybe_default_option): Pass true to handle_generated_option GENERATED_P. * optc-gen.awk: Likewise. ada/ * gcc-interface/misc.c (gnat_handle_option): Pass true to handle_generated_option GENERATED_P. testsuite/ * gcc.dg/pr79677.c: New test. --- gcc/opts.h.jj 2017-01-01 12:45:38.000000000 +0100 +++ gcc/opts.h 2017-02-24 16:30:05.287564997 +0100 @@ -353,7 +353,7 @@ bool handle_generated_option (struct gcc size_t opt_index, const char *arg, int value, unsigned int lang_mask, int kind, location_t loc, const struct cl_option_handlers *handlers, - diagnostic_context *dc); + bool generated_p, diagnostic_context *dc); void generate_option (size_t opt_index, const char *arg, int value, unsigned int lang_mask, struct cl_decoded_option *decoded); --- gcc/opts-common.c.jj 2017-01-01 12:45:39.000000000 +0100 +++ gcc/opts-common.c 2017-02-24 16:40:35.878378793 +0100 @@ -959,9 +959,10 @@ keep: option for options from the source file, UNKNOWN_LOCATION otherwise. GENERATED_P is true for an option generated as part of processing another option or otherwise generated internally, false - for one explicitly passed by the user. Returns false if the switch - was invalid. DC is the diagnostic context for options affecting - diagnostics state, or NULL. */ + for one explicitly passed by the user. control_warning_option + generated options are considered explicitly passed by the user. + Returns false if the switch was invalid. DC is the diagnostic + context for options affecting diagnostics state, or NULL. */ static bool handle_option (struct gcc_options *opts, @@ -1005,13 +1006,13 @@ handle_generated_option (struct gcc_opti size_t opt_index, const char *arg, int value, unsigned int lang_mask, int kind, location_t loc, const struct cl_option_handlers *handlers, - diagnostic_context *dc) + bool generated_p, diagnostic_context *dc) { struct cl_decoded_option decoded; generate_option (opt_index, arg, value, lang_mask, &decoded); return handle_option (opts, opts_set, &decoded, lang_mask, kind, loc, - handlers, true, dc); + handlers, generated_p, dc); } /* Fill in *DECODED with an option described by OPT_INDEX, ARG and @@ -1503,7 +1504,7 @@ control_warning_option (unsigned int opt handle_generated_option (opts, opts_set, opt_index, arg, value, lang_mask, - kind, loc, handlers, dc); + kind, loc, handlers, false, dc); } } } --- gcc/opts.c.jj 2017-01-30 19:10:51.000000000 +0100 +++ gcc/opts.c 2017-02-24 16:30:38.168137303 +0100 @@ -403,13 +403,13 @@ maybe_default_option (struct gcc_options handle_generated_option (opts, opts_set, default_opt->opt_index, default_opt->arg, default_opt->value, lang_mask, DK_UNSPECIFIED, loc, - handlers, dc); + handlers, true, dc); else if (default_opt->arg == NULL && !option->cl_reject_negative) handle_generated_option (opts, opts_set, default_opt->opt_index, default_opt->arg, !default_opt->value, lang_mask, DK_UNSPECIFIED, loc, - handlers, dc); + handlers, true, dc); } /* As indicated by the optimization level LEVEL (-Os if SIZE is set, --- gcc/optc-gen.awk.jj 2017-01-04 22:26:21.000000000 +0100 +++ gcc/optc-gen.awk 2017-02-24 16:42:30.570895725 +0100 @@ -444,7 +444,7 @@ for (i = 0; i < n_enabledby; i++) { print " if (" condition ")" print " handle_generated_option (opts, opts_set," print " " opt_enum(thisenable[j]) ", NULL, " value "," - print " lang_mask, kind, loc, handlers, dc);" + print " lang_mask, kind, loc, handlers, true, dc);" } else { print "#error " thisenable[j] " does not have a Var() flag" } @@ -497,7 +497,7 @@ for (i = 0; i < n_langs; i++) { print " if (!opts_set->x_" opt_var_name ")" print " handle_generated_option (opts, opts_set," print " " opt_enum(thisenable_opt) ", NULL, " value "," - print " lang_mask, kind, loc, handlers, dc);" + print " lang_mask, kind, loc, handlers, true, dc);" } else { print "#error " thisenable_opt " does not have a Var() flag" } --- gcc/ada/gcc-interface/misc.c.jj 2016-10-31 20:34:12.000000000 +0100 +++ gcc/ada/gcc-interface/misc.c 2017-02-24 16:37:32.987743720 +0100 @@ -149,7 +149,7 @@ gnat_handle_option (size_t scode, const handle_generated_option (&global_options, &global_options_set, OPT_Wunused, NULL, value, gnat_option_lang_mask (), kind, loc, - handlers, global_dc); + handlers, true, global_dc); warn_uninitialized = value; warn_maybe_uninitialized = value; break; --- gcc/testsuite/gcc.dg/pr79677.c.jj 2017-02-24 16:46:10.694049351 +0100 +++ gcc/testsuite/gcc.dg/pr79677.c 2017-02-24 16:45:43.000000000 +0100 @@ -0,0 +1,15 @@ +/* PR c/79677 */ +/* { dg-do compile } */ +/* { dg-options "-Wformat -Werror=format-security -Wformat" } */ +/* { dg-message "some warnings being treated as errors" "" { target *-*-* } 0 } */ + +void foo (char *); + +int +main () +{ + char s[10] = "%s"; + foo (s); + __builtin_printf (s); /* { dg-error "format not a string literal and no format arguments" } */ + return 0; +} Jakub