This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Add a __nowarn__ keyword


> | I'm working on it now.
> 
> awesome!

How's this look?  The classification state change tree is in the
diagnostic context, but the actual structure is opaque.  The push/pop
stack is separate, stored in c-pragma.c.  This way, the save/restore
can be used for scope-level diagnostic state once we figure out how to
define that, via a (save A, restore B, restore A) for now.  At some
point, I suppose we could pass the state pointer itself to the
diagnostic reporting functions.


Index: diagnostic.h
===================================================================
--- diagnostic.h	(revision 127325)
+++ diagnostic.h	(working copy)
@@ -53,12 +53,15 @@ typedef struct
 /*  Forward declarations.  */
 typedef struct diagnostic_context diagnostic_context;
 typedef void (*diagnostic_starter_fn) (diagnostic_context *,
 				       diagnostic_info *);
 typedef diagnostic_starter_fn diagnostic_finalizer_fn;
 
+/* The diagnostic state is an opaque pointer.  */
+struct diagnostic_classification_state_t;
+
 /* This data structure bundles altogether any information relevant to
    the context of a diagnostic message.  */
 struct diagnostic_context
 {
   /* Where most of the diagnostic formatting work is done.  */
   pretty_printer *printer;
@@ -77,12 +80,15 @@ struct diagnostic_context
      (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 <options.h>.  */
   char classify_diagnostic[N_OPTS];
 
+  /* If non-NULL, this is the current state of changes to the above.  */
+  struct diagnostic_classification_state_t *classification_state;
+
   /* True if we should print the command line option which controls
      each diagnostic, if known.  */
   bool show_option_requested;
 
   /* True if we should raise a SIGABRT on errors.  */
   bool abort_on_error;
@@ -188,12 +194,24 @@ extern void diagnostic_report_current_mo
 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 */);
+
+/* This returns a token which represents the current state of the
+   diagnostic classifications.  */
+extern struct diagnostic_classification_state_t *
+  diagnostic_save_classifications (diagnostic_context *context);
+
+/* This returns the classifications to some previous point.  Further
+   changes to the classifications will be relative to this previous
+   point.  */
+extern void diagnostic_restore_classifications (diagnostic_context *context,
+						struct diagnostic_classification_state_t *);
+
 extern void diagnostic_report_diagnostic (diagnostic_context *,
 					  diagnostic_info *);
 #ifdef ATTRIBUTE_GCC_DIAG
 extern void diagnostic_set_info (diagnostic_info *, const char *, va_list *,
 				 location_t, diagnostic_t) ATTRIBUTE_GCC_DIAG(2,0);
 extern void diagnostic_set_info_translated (diagnostic_info *, const char *,
Index: diagnostic.c
===================================================================
--- diagnostic.c	(revision 127325)
+++ diagnostic.c	(working copy)
@@ -39,12 +39,19 @@ along with GCC; see the file COPYING3.  
 #include "diagnostic.h"
 #include "langhooks.h"
 #include "langhooks-def.h"
 #include "opts.h"
 
 
+typedef struct diagnostic_classification_state_t {
+  struct diagnostic_classification_state_t *previous;
+  int option_index;
+  int kind;
+} diagnostic_classification_state_t;
+
+
 /* Prototypes.  */
 static char *build_message_string (const char *, ...) ATTRIBUTE_PRINTF_1;
 
 static void default_diagnostic_starter (diagnostic_context *,
 					diagnostic_info *);
 static void default_diagnostic_finalizer (diagnostic_context *,
@@ -53,12 +60,13 @@ static void default_diagnostic_finalizer
 static void error_recursion (diagnostic_context *) ATTRIBUTE_NORETURN;
 static bool diagnostic_count_diagnostic (diagnostic_context *,
 					 diagnostic_info *);
 static void diagnostic_action_after_output (diagnostic_context *,
 					    diagnostic_info *);
 static void real_abort (void) ATTRIBUTE_NORETURN;
+static int lookup_classification (diagnostic_context *, int);
 
 /* A diagnostic_context surrogate for stderr.  */
 static diagnostic_context global_diagnostic_context;
 diagnostic_context *global_dc = &global_diagnostic_context;
 
 
@@ -325,17 +333,75 @@ diagnostic_classify_diagnostic (diagnost
 
   if (option_index <= 0
       || option_index >= N_OPTS
       || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
     return DK_UNSPECIFIED;
 
+  if (context->classification_state)
+    {
+      struct diagnostic_classification_state_t *state;
+
+      old_kind = lookup_classification (context, option_index);
+      state = (struct diagnostic_classification_state_t *)
+	xmalloc (sizeof (struct diagnostic_classification_state_t));
+
+      state->previous = context->classification_state;
+      state->option_index = option_index;
+      state->kind = new_kind;
+      context->classification_state = state;
+
+      return old_kind;
+    }
+
   old_kind = context->classify_diagnostic[option_index];
   context->classify_diagnostic[option_index] = new_kind;
   return old_kind;
 }
 
+static int
+lookup_classification (diagnostic_context * context, int option_index)
+{
+  if (option_index <= 0
+      || option_index >= N_OPTS)
+    return DK_UNSPECIFIED;
+
+  if (context->classification_state)
+    {
+      diagnostic_classification_state_t *s;
+      for (s = context->classification_state;
+	   s; s = s->previous)
+	{
+	  if (s->option_index == option_index)
+	    return s->kind;
+	}
+    }
+  return context->classify_diagnostic[option_index];
+}
+
+struct diagnostic_classification_state_t *
+diagnostic_save_classifications (diagnostic_context *context)
+{
+  if (context->classification_state == NULL)
+    {
+      /* Create the head of the chain.  */
+      context->classification_state = (struct diagnostic_classification_state_t *)
+	xmalloc (sizeof (struct diagnostic_classification_state_t));
+      context->classification_state->previous = NULL;
+      context->classification_state->option_index = 0;
+      context->classification_state->kind = context->classify_diagnostic[0];
+    }
+  return context->classification_state;
+}
+
+void
+diagnostic_restore_classifications (diagnostic_context *context,
+				    struct diagnostic_classification_state_t *state)
+{
+  context->classification_state = state;
+}
+
 /* 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
    front-end independent format specifiers are exactly those described
    in the documentation of output_format.  */
 
@@ -372,21 +438,23 @@ diagnostic_report_diagnostic (diagnostic
       diagnostic->kind = DK_ERROR;
       maybe_print_warnings_as_errors_message = true;
     }
   
   if (diagnostic->option_index)
     {
+      int kind;
       /* 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)
+      kind = lookup_classification (context, diagnostic->option_index);
+      if (kind != DK_UNSPECIFIED)
 	{
-	  diagnostic->kind = context->classify_diagnostic[diagnostic->option_index];
+	  diagnostic->kind = kind;
 	  maybe_print_warnings_as_errors_message = false;
 	}
       /* This allows for future extensions, like temporarily disabling
 	 warnings for ranges of source code.  */
       if (diagnostic->kind == DK_IGNORED)
 	return;
Index: c-pragma.c
===================================================================
--- c-pragma.c	(revision 127325)
+++ c-pragma.c	(working copy)
@@ -814,31 +814,62 @@ handle_pragma_visibility (cpp_reader *du
   if (pragma_lex (&x) != CPP_EOF)
     warning (OPT_Wpragmas, "junk at end of %<#pragma GCC visibility%>");
 }
 
 #endif
 
+typedef struct diagnostic_stack_entry_t {
+  struct diagnostic_stack_entry_t *previous;
+  struct diagnostic_classification_state_t *state;
+} diagnostic_stack_entry_t;
+
+static diagnostic_stack_entry_t *diagnostic_stack = 0;
+
 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;
+  diagnostic_stack_entry_t *stack;
 
   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, "push") == 0)
+    {
+      stack = (diagnostic_stack_entry_t *) xmalloc (sizeof (diagnostic_stack_entry_t));
+      stack->previous = diagnostic_stack;
+      stack->state = diagnostic_save_classifications (global_dc);
+      diagnostic_stack = stack;
+      return;
+    }
+  else if (strcmp (kind_string, "pop") == 0)
+    {
+      stack = diagnostic_stack;
+      if (!stack)
+	{
+	  error ("$pragma GCC diagnostic pop with no matching push");
+	  return;
+	}
+      diagnostic_stack = stack->previous;
+      diagnostic_restore_classifications (global_dc, stack->state);
+      free (stack);
+      return;
+    }
+
   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;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]