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;
+}

Reply via email to