From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7982 invoked by alias); 10 Aug 2007 03:28:46 -0000 Received: (qmail 7761 invoked by uid 22791); 10 Aug 2007 03:28:45 -0000 X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org (qpsmtpd/0.31) with ESMTP; Fri, 10 Aug 2007 03:28:41 +0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.13.1/8.13.1) with ESMTP id l7A3RVsE028905; Thu, 9 Aug 2007 23:27:31 -0400 Received: from post-office.corp.redhat.com (post-office.corp.redhat.com [10.11.254.111]) by int-mx1.corp.redhat.com (8.13.1/8.13.1) with ESMTP id l7A3RVdB030029; Thu, 9 Aug 2007 23:27:31 -0400 Received: from greed.delorie.com (vpn-14-110.rdu.redhat.com [10.11.14.110]) by post-office.corp.redhat.com (8.13.8/8.13.8) with ESMTP id l7A3RV8h008564; Thu, 9 Aug 2007 23:27:31 -0400 Received: from greed.delorie.com (greed.delorie.com [127.0.0.1]) by greed.delorie.com (8.13.8/8.13.8) with ESMTP id l7A3RUjB005256; Thu, 9 Aug 2007 23:27:30 -0400 Received: (from dj@localhost) by greed.delorie.com (8.13.8/8.13.8/Submit) id l7A3RUbm005253; Thu, 9 Aug 2007 23:27:30 -0400 Date: Fri, 10 Aug 2007 03:28:00 -0000 Message-Id: <200708100327.l7A3RUbm005253@greed.delorie.com> From: DJ Delorie To: gdr@cs.tamu.edu CC: mark@codesourcery.com, lopezibanez@gmail.com, ghazi@caip.rutgers.edu, gcc-patches@gcc.gnu.org In-reply-to: (message from Gabriel Dos Reis on Thu, 9 Aug 2007 22:09:27 -0500 (CDT)) Subject: Re: Add a __nowarn__ keyword References: <46B9F0B5.1080302@gnu.org> <200708082254.l78MsIC8014802@greed.delorie.com> <20070809134017.GA10368@caradoc.them.org> <20070809143028.GA14681@caradoc.them.org> <6c33472e0708090805t210191f6r63832af3afdd0816@mail.gmail.com> <200708091531.l79FVI4w032104@greed.delorie.com> <46BB93CD.7070300@codesourcery.com> <87hcn8885y.fsf@soliton.cs.tamu.edu> <200708100200.l7A20oe8001939@greed.delorie.com> X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2007-08/txt/msg00636.txt.bz2 > | 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 . */ 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;