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: pragma diagnostic push/pop


What happened with this?

Manuel.

On 11 June 2010 23:28, DJ Delorie <dj@redhat.com> wrote:
>
>> I forgot to mention: at the very least I think the diagnostic routines
>> should take the location as a parameter. ?If we must use input_location,
>> let it be in the callers.
>
> I did it that way. ?I assume there are FAR more callers of pragma_lex()
> than the three diagnostic*() calls here.
>
>
> ? ? ? ?* diagnostic.h (diagnostic_classification_change_t): New.
> ? ? ? ?(diagnostic_context): Add history and push/pop list.
> ? ? ? ?(diagnostic_push_diagnostics): Declare.
> ? ? ? ?(diagnostic_pop_diagnostics): Declare.
> ? ? ? ?* diagnostic.c (diagnostic_classify_diagnostic): Store changes
> ? ? ? ?from pragmas in a history chain instead of the global table.
> ? ? ? ?(diagnostic_push_diagnostics): New.
> ? ? ? ?(diagnostic_pop_diagnostics): New.
> ? ? ? ?(diagnostic_report_diagnostic): Scan history chain to find state
> ? ? ? ?of diagnostics as of the diagnostic location.
> ? ? ? ?* opts.c (set_option): Pass UNKNOWN_LOCATION to
> ? ? ? ?diagnostic_classify_diagnostic.
> ? ? ? ?(enable_warning_as_error): Likewise.
> ? ? ? ?* diagnostic-core.h (DK_POP): Add after "real" diagnostics, for
> ? ? ? ?use in the history chain.
> ? ? ? ?* c-family/c-pragma.c (handle_pragma_diagnostic): Add push/pop,
> ? ? ? ?allow these pragmas anywhere.
> ? ? ? ?* doc/extend.texi: Document pragma GCC diagnostic changes.
>
> ? ? ? ?* gcc.dg/pragma-diag-1.c: New.
>
> Index: doc/extend.texi
> ===================================================================
> --- doc/extend.texi ? ? (revision 160588)
> +++ doc/extend.texi ? ? (working copy)
> @@ -12587,21 +12587,36 @@ option.
> ?@example
> ?#pragma GCC diagnostic warning "-Wformat"
> ?#pragma GCC diagnostic error "-Wformat"
> ?#pragma GCC diagnostic ignored "-Wformat"
> ?@end example
>
> -Note that these pragmas override any command-line options. ?Also,
> -while it is syntactically valid to put these pragmas anywhere in your
> -sources, the only supported location for them is before any data or
> -functions are defined. ?Doing otherwise may result in unpredictable
> -results depending on how the optimizer manages your sources. ?If the
> -same option is listed multiple times, the last one specified is the
> -one that is in effect. ?This pragma is not intended to be a general
> -purpose replacement for command-line options, but for implementing
> -strict control over project policies.
> +Note that these pragmas override any command-line options. ?GCC keeps
> +track of the location of each pragma, and issues diagnostics according
> +to the state as of that point in the source file. ?Thus, pragmas occurring
> +after a line do not affect diagnostics caused by that line.
> +
> +@item #pragma GCC diagnostic push
> +@itemx #pragma GCC diagnostic pop
> +
> +Causes GCC to remember the state of the diagnostics as of each
> +@code{push}, and restore to that point at each @code{pop}. ?If a
> +@code{pop} has no matching @code{push}, the command line options are
> +restored.
> +
> +@example
> +#pragma GCC diagnostic error "-Wuninitialized"
> + ?foo(a); ? ? ? ? ? ? ? ? ? ? ?/* error is given for this one */
> +#pragma GCC diagnostic push
> +#pragma GCC diagnostic ignored "-Wuninitialized"
> + ?foo(b); ? ? ? ? ? ? ? ? ? ? ?/* no diagnostic for this one */
> +#pragma GCC diagnostic pop
> + ?foo(c); ? ? ? ? ? ? ? ? ? ? ?/* error is given for this one */
> +#pragma GCC diagnostic pop
> + ?foo(d); ? ? ? ? ? ? ? ? ? ? ?/* depends on command line options */
> +@end example
>
> ?@end table
>
> ?GCC also offers a simple mechanism for printing messages during
> ?compilation.
>
> Index: c-family/c-pragma.c
> ===================================================================
> --- c-family/c-pragma.c (revision 160588)
> +++ c-family/c-pragma.c (working copy)
> @@ -703,40 +703,44 @@ handle_pragma_diagnostic(cpp_reader *ARG
> ? const char *kind_string, *option_string;
> ? unsigned int option_index;
> ? enum cpp_ttype token;
> ? diagnostic_t kind;
> ? tree x;
>
> - ?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, "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 if (strcmp (kind_string, "push") == 0)
> + ? ?{
> + ? ? ?diagnostic_push_diagnostics (global_dc, input_location);
> + ? ? ?return;
> + ? ?}
> + ?else if (strcmp (kind_string, "pop") == 0)
> + ? ?{
> + ? ? ?diagnostic_pop_diagnostics (global_dc, input_location);
> + ? ? ?return;
> + ? ?}
> ? else
> - ? ?GCC_BAD ("expected [error|warning|ignored] after %<#pragma GCC diagnostic%>");
> + ? ?GCC_BAD ("expected [error|warning|ignored|push|pop] 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++)
> ? ? if (strcmp (cl_options[option_index].opt_text, option_string) == 0)
> ? ? ? {
> ? ? ? ?/* This overrides -Werror, for example. ?*/
> - ? ? ? diagnostic_classify_diagnostic (global_dc, option_index, kind);
> + ? ? ? diagnostic_classify_diagnostic (global_dc, option_index, kind, input_location);
> ? ? ? ?/* This makes sure the option is enabled, like -Wfoo would do. ?*/
> ? ? ? ?if (cl_options[option_index].var_type == CLVC_BOOLEAN
> ? ? ? ? ? ?&& cl_options[option_index].flag_var
> ? ? ? ? ? ?&& kind != DK_IGNORED)
> ? ? ? ? ? ?*(int *) cl_options[option_index].flag_var = 1;
> ? ? ? ?return;
> Index: diagnostic.c
> ===================================================================
> --- diagnostic.c ? ? ? ?(revision 160588)
> +++ diagnostic.c ? ? ? ?(working copy)
> @@ -303,26 +303,83 @@ default_diagnostic_finalizer (diagnostic
> ?/* Interface to specify diagnostic kind overrides. ?Returns the
> ? ?previous setting, or DK_UNSPECIFIED if the parameters are out of
> ? ?range. ?*/
> ?diagnostic_t
> ?diagnostic_classify_diagnostic (diagnostic_context *context,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?int option_index,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? diagnostic_t new_kind)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? diagnostic_t new_kind,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? location_t where)
> ?{
> ? diagnostic_t old_kind;
>
> ? if (option_index <= 0
> ? ? ? || option_index >= context->n_opts
> ? ? ? || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
> ? ? return DK_UNSPECIFIED;
>
> ? old_kind = context->classify_diagnostic[option_index];
> - ?context->classify_diagnostic[option_index] = new_kind;
> +
> + ?/* Handle pragmas separately, since we need to keep track of *where*
> + ? ? the pragmas were. ?*/
> + ?if (where != UNKNOWN_LOCATION)
> + ? ?{
> + ? ? ?int i;
> +
> + ? ? ?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;
> + ? ? ? ? }
> +
> + ? ? ?i = context->n_classification_history;
> + ? ? ?context->classification_history =
> + ? ? ? (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?* sizeof (diagnostic_classification_change_t));
> + ? ? ?context->classification_history[i].location = where;
> + ? ? ?context->classification_history[i].option = option_index;
> + ? ? ?context->classification_history[i].kind = new_kind;
> + ? ? ?context->n_classification_history ++;
> + ? ?}
> + ?else
> + ? ?context->classify_diagnostic[option_index] = new_kind;
> +
> ? return old_kind;
> ?}
>
> +/* Save all diagnostic classifications in a stack. ?*/
> +void
> +diagnostic_push_diagnostics (diagnostic_context *context, location_t where ATTRIBUTE_UNUSED)
> +{
> + ?context->push_list = (int *) xrealloc (context->push_list, (context->n_push + 1) * sizeof (int));
> + ?context->push_list[context->n_push ++] = context->n_classification_history;
> +}
> +
> +/* Restore the topmost classification set off the stack. ?If the stack
> + ? is empty, revert to the state based on command line parameters. ?*/
> +void
> +diagnostic_pop_diagnostics (diagnostic_context *context, location_t where)
> +{
> + ?int jump_to;
> + ?int i;
> +
> + ?if (context->n_push)
> + ? ?jump_to = context->push_list [-- context->n_push];
> + ?else
> + ? ?jump_to = 0;
> +
> + ?i = context->n_classification_history;
> + ?context->classification_history =
> + ? ?(diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?* sizeof (diagnostic_classification_change_t));
> + ?context->classification_history[i].location = where;
> + ?context->classification_history[i].option = jump_to;
> + ?context->classification_history[i].kind = DK_POP;
> + ?context->n_classification_history ++;
> +}
> +
> ?/* 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.
> ? ?Return true if a diagnostic was printed, false otherwise. ?*/
> @@ -371,19 +428,47 @@ diagnostic_report_diagnostic (diagnostic
> ? ? {
> ? ? ? diagnostic->kind = DK_ERROR;
> ? ? }
>
> ? if (diagnostic->option_index)
> ? ? {
> + ? ? ?diagnostic_t diag_class = DK_UNSPECIFIED;
> +
> ? ? ? /* This tests if the user provided the appropriate -Wfoo or
> ? ? ? ? -Wno-foo option. ?*/
> ? ? ? if (! context->option_enabled (diagnostic->option_index))
> ? ? ? ?return false;
> +
> + ? ? ?/* This tests for #pragma diagnostic changes. ?*/
> + ? ? ?if (context->n_classification_history > 0)
> + ? ? ? {
> + ? ? ? ? int i;
> + ? ? ? ? /* FIXME: Stupid search. ?Optimize later. */
> + ? ? ? ? for (i = context->n_classification_history - 1; i >= 0; i --)
> + ? ? ? ? ? {
> + ? ? ? ? ? ? if (context->classification_history[i].location <= location)
> + ? ? ? ? ? ? ? {
> + ? ? ? ? ? ? ? ? if (context->classification_history[i].kind == (int) DK_POP)
> + ? ? ? ? ? ? ? ? ? {
> + ? ? ? ? ? ? ? ? ? ? i = context->classification_history[i].option;
> + ? ? ? ? ? ? ? ? ? ? continue;
> + ? ? ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? ? if (context->classification_history[i].option == diagnostic->option_index)
> + ? ? ? ? ? ? ? ? ? {
> + ? ? ? ? ? ? ? ? ? ? diag_class = context->classification_history[i].kind;
> + ? ? ? ? ? ? ? ? ? ? if (diag_class != DK_UNSPECIFIED)
> + ? ? ? ? ? ? ? ? ? ? ? diagnostic->kind = diag_class;
> + ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? }
> + ? ? ? }
> ? ? ? /* This tests if the user provided the appropriate -Werror=foo
> ? ? ? ? option. ?*/
> - ? ? ?if (context->classify_diagnostic[diagnostic->option_index] != DK_UNSPECIFIED)
> + ? ? ?if (diag_class == DK_UNSPECIFIED
> + ? ? ? ? && context->classify_diagnostic[diagnostic->option_index] != DK_UNSPECIFIED)
> ? ? ? ?{
> ? ? ? ? ?diagnostic->kind = context->classify_diagnostic[diagnostic->option_index];
> ? ? ? ?}
> ? ? ? /* This allows for future extensions, like temporarily disabling
> ? ? ? ? warnings for ranges of source code. ?*/
> ? ? ? if (diagnostic->kind == DK_IGNORED)
> Index: diagnostic.h
> ===================================================================
> --- diagnostic.h ? ? ? ?(revision 160588)
> +++ diagnostic.h ? ? ? ?(working copy)
> @@ -38,12 +38,22 @@ typedef struct diagnostic_info
> ? /* The kind of diagnostic it is about. ?*/
> ? diagnostic_t kind;
> ? /* Which OPT_* directly controls this diagnostic. ?*/
> ? int option_index;
> ?} diagnostic_info;
>
> +/* Each time a diagnostic's classification is changed with a pragma,
> + ? we record the change and the location of the change in an array of
> + ? these structs. ?*/
> +typedef struct diagnostic_classification_change_t
> +{
> + ?location_t location;
> + ?int option;
> + ?diagnostic_t kind;
> +} diagnostic_classification_change_t;
> +
> ?/* ?Forward declarations. ?*/
> ?typedef struct diagnostic_context diagnostic_context;
> ?typedef void (*diagnostic_starter_fn) (diagnostic_context *,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? diagnostic_info *);
> ?typedef diagnostic_starter_fn diagnostic_finalizer_fn;
>
> @@ -73,12 +83,26 @@ struct diagnostic_context
> ? ? ?options), 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. ?*/
> ? diagnostic_t *classify_diagnostic;
>
> + ?/* History of all changes to the classifications above. ?This list
> + ? ? is stored in location-order, so we can search it, either
> + ? ? binary-wise or end-to-front, to find the most recent
> + ? ? classification for a given diagnostic, given the location of the
> + ? ? diagnostic. ?*/
> + ?diagnostic_classification_change_t *classification_history;
> +
> + ?/* The size of the above array. ?*/
> + ?int n_classification_history;
> +
> + ?/* For pragma push/pop. ?*/
> + ?int *push_list;
> + ?int n_push;
> +
> ? /* 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;
> @@ -225,13 +249,16 @@ extern void diagnostic_initialize (diagn
> ?extern void diagnostic_finish (diagnostic_context *);
> ?extern void diagnostic_report_current_module (diagnostic_context *);
>
> ?/* Force diagnostics controlled by OPTIDX to be kind KIND. ?*/
> ?extern diagnostic_t diagnostic_classify_diagnostic (diagnostic_context *,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?int /* optidx */,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? diagnostic_t /* kind */);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? diagnostic_t /* kind */,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? location_t);
> +extern void diagnostic_push_diagnostics (diagnostic_context *, location_t);
> +extern void diagnostic_pop_diagnostics (diagnostic_context *, location_t);
> ?extern bool 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-core.h
> ===================================================================
> --- diagnostic-core.h ? (revision 160588)
> +++ diagnostic-core.h ? (working copy)
> @@ -29,13 +29,16 @@ along with GCC; see the file COPYING3.
> ?/* Constants used to discriminate diagnostics. ?*/
> ?typedef enum
> ?{
> ?#define DEFINE_DIAGNOSTIC_KIND(K, msgid) K,
> ?#include "diagnostic.def"
> ?#undef DEFINE_DIAGNOSTIC_KIND
> - ?DK_LAST_DIAGNOSTIC_KIND
> + ?DK_LAST_DIAGNOSTIC_KIND,
> + ?/* This is used for tagging pragma pops in the diagnostic
> + ? ? classification history chain. ?*/
> + ?DK_POP
> ?} diagnostic_t;
>
> ?extern const char *progname;
>
> ?extern const char *trim_filename (const char *);
>
> Index: testsuite/gcc.dg/pragma-diag-1.c
> ===================================================================
> --- testsuite/gcc.dg/pragma-diag-1.c ? ?(revision 0)
> +++ testsuite/gcc.dg/pragma-diag-1.c ? ?(revision 0)
> @@ -0,0 +1,21 @@
> +/* { dg-do compile } */
> +/* { dg-options "-Wuninitialized -O2" } */
> +/* { dg-message "warnings being treated as errors" "" {target "*-*-*"} 0 } */
> +
> +main()
> +{
> + ?int a;
> + ?int b;
> + ?int c;
> + ?int d;
> +
> +#pragma GCC diagnostic error "-Wuninitialized"
> + ?foo(a); ? ? ? ? ? ? ? ? ? ? ?/* { dg-error "uninitialized" } */
> +#pragma GCC diagnostic push
> +#pragma GCC diagnostic ignored "-Wuninitialized"
> + ?foo(b);
> +#pragma GCC diagnostic pop
> + ?foo(c); ? ? ? ? ? ? ? ? ? ? ?/* { dg-error "uninitialized" } */
> +#pragma GCC diagnostic pop
> + ?foo(d); ? ? ? ? ? ? ? ? ? ? ?/* { dg-warning "uninitialized" } */
> +}
> Index: opts.c
> ===================================================================
> --- opts.c ? ? ?(revision 160588)
> +++ opts.c ? ? ?(working copy)
> @@ -2473,13 +2473,14 @@ set_option (int opt_index, int value, co
> ? ? case CLVC_STRING:
> ? ? ? ?*(const char **) option->flag_var = arg;
> ? ? ? ?break;
> ? ? }
>
> ? if ((diagnostic_t)kind != DK_UNSPECIFIED)
> - ? ?diagnostic_classify_diagnostic (global_dc, opt_index, (diagnostic_t)kind);
> + ? ?diagnostic_classify_diagnostic (global_dc, opt_index, (diagnostic_t)kind,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? UNKNOWN_LOCATION);
> ?}
>
>
> ?/* Callback function, called when -Werror= enables a warning. ?*/
>
> ?static void (*warning_as_error_callback) (int) = NULL;
> @@ -2511,13 +2512,14 @@ enable_warning_as_error (const char *arg
> ? ? ? error ("-Werror=%s: No option -%s", arg, new_option);
> ? ? }
> ? else
> ? ? {
> ? ? ? const diagnostic_t kind = value ? DK_ERROR : DK_WARNING;
>
> - ? ? ?diagnostic_classify_diagnostic (global_dc, option_index, kind);
> + ? ? ?diagnostic_classify_diagnostic (global_dc, option_index, kind,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? UNKNOWN_LOCATION);
> ? ? ? if (kind == DK_ERROR)
> ? ? ? ?{
> ? ? ? ? ?const struct cl_option * const option = cl_options + option_index;
>
> ? ? ? ? ?/* -Werror=foo implies -Wfoo. ?*/
> ? ? ? ? ?if (option->var_type == CLVC_BOOLEAN)
>


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