The idea is that when we see a change of classification, and the option was originally unspecified, we record the command-line status. This way, when doing pop later, we already check if the option was reclassified so we get the command-line status. This also works with -Wall, since all dependent options go through set_option and call diagnostic_classify_diagnostic. But we have to call it before changing the option status.
Bootstrapped and regression tested on x86_64-linux-gnu. OK? gcc/ChangeLog: 2014-08-19 Manuel López-Ibáñez <m...@gcc.gnu.org> PR c/59304 * opts-common.c (set_option): Call diagnostic_classify_diagnostic before setting the option. * diagnostic.c (diagnostic_classify_diagnostic): Record command-line status. gcc/testsuite/ChangeLog: 2014-08-19 Manuel López-Ibáñez <m...@gcc.gnu.org> PR c/59304 * gcc.dg/pr59304.c: New test.
Index: gcc/opts-common.c =================================================================== --- gcc/opts-common.c (revision 214136) +++ gcc/opts-common.c (working copy) @@ -1117,10 +1117,13 @@ set_option (struct gcc_options *opts, st void *set_flag_var = NULL; if (!flag_var) return; + if ((diagnostic_t) kind != DK_UNSPECIFIED && dc != NULL) + diagnostic_classify_diagnostic (dc, opt_index, (diagnostic_t) kind, loc); + if (opts_set != NULL) set_flag_var = option_flag_var (opt_index, opts_set); switch (option->var_type) { @@ -1196,14 +1199,10 @@ set_option (struct gcc_options *opts, st if (set_flag_var) *(void **) set_flag_var = v; } break; } - - if ((diagnostic_t) kind != DK_UNSPECIFIED - && dc != NULL) - diagnostic_classify_diagnostic (dc, opt_index, (diagnostic_t) kind, loc); } /* Return the address of the flag variable for option OPT_INDEX in options structure OPTS, or NULL if there is no flag variable. */ Index: gcc/diagnostic.c =================================================================== --- gcc/diagnostic.c (revision 214136) +++ gcc/diagnostic.c (working copy) @@ -582,10 +582,19 @@ diagnostic_classify_diagnostic (diagnost the pragmas were. */ if (where != UNKNOWN_LOCATION) { int i; + /* Record the command-line status, so we can reset it back on DK_POP. */ + if (old_kind == DK_UNSPECIFIED) + { + old_kind = context->option_enabled (option_index, + context->option_state) + ? DK_WARNING : DK_IGNORED; + context->classify_diagnostic[option_index] = old_kind; + } + for (i = context->n_classification_history - 1; i >= 0; i --) if (context->classification_history[i].option == option_index) { old_kind = context->classification_history[i].kind; break; Index: gcc/testsuite/gcc.dg/pr59304.c =================================================================== --- gcc/testsuite/gcc.dg/pr59304.c (revision 0) +++ gcc/testsuite/gcc.dg/pr59304.c (revision 0) @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +enum EE + { + ONE, TWO, THREE + }; + +int f (enum EE e) +{ + int r = 0; + +#pragma GCC diagnostic push +#pragma GCC diagnostic error "-Wswitch-enum" + + switch (e) + { + case ONE: + r = 1; + break; + case TWO: + r = 2; + break; + case THREE: + r = 3; + break; + } + +#pragma GCC diagnostic pop + + switch (e) + { + case ONE: + r = 1; + break; + case TWO: + r = 2; + break; + } + + return r; +}