This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Add a __nowarn__ keyword
Here's the latest patch, with push/pop, push+change, and undo
(commented out).
Index: diagnostic.h
===================================================================
--- diagnostic.h (revision 127330)
+++ diagnostic.h (working copy)
@@ -53,12 +53,19 @@ 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. */
+typedef struct diagnostic_classification_state_t {
+ struct diagnostic_classification_state_t *previous;
+ int option_index;
+ int kind;
+} 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 +84,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. */
+ 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 +198,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 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,
+ 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 127330)
+++ diagnostic.c (working copy)
@@ -53,12 +53,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 +326,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)
+ {
+ diagnostic_classification_state_t *state;
+
+ old_kind = lookup_classification (context, option_index);
+ state = (diagnostic_classification_state_t *)
+ xmalloc (sizeof (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];
+}
+
+diagnostic_classification_state_t *
+diagnostic_save_classifications (diagnostic_context *context)
+{
+ if (context->classification_state == NULL)
+ {
+ /* Create the head of the chain. */
+ context->classification_state = (diagnostic_classification_state_t *)
+ xmalloc (sizeof (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,
+ 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 +431,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 127330)
+++ c-pragma.c (working copy)
@@ -814,39 +814,91 @@ 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;
+
+ token = pragma_lex (&x);
+ if (token != CPP_NAME)
+ return;
+ kind_string = IDENTIFIER_POINTER (x);
+ }
+ 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 0
+ /* This is an example of how to do this, in case we decide to need
+ this functionality in the future. "undo" moves one state up the
+ tree, effectively undoing the previous pragma. It relies on
+ every pragma being in the state tree (which may be expensive), so
+ we must force the tree to exist somehow. */
+ else if (strcmp (kind_string, "undo") == 0)
+ {
+ diagnostic_classification_state_t *state;
+ state = diagnostic_save_classifications (global_dc);
+ state = state->previous;
+ diagnostic_restore_classifications (global_dc, state);
+ return;
+ }
+ /* Here we force the state tree to exist for any change-type pragma. */
+ diagnostic_save_classifications (global_dc);
+#endif
+
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%>");
+ GCC_BAD ("expected [push|pop|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++)