diff options
author | DJ Delorie <dj@redhat.com> | 2010-06-21 16:58:57 -0400 |
---|---|---|
committer | DJ Delorie <dj@gcc.gnu.org> | 2010-06-21 16:58:57 -0400 |
commit | cd7fe53b723e8f24dc2efc21bc68a2ac174ee882 (patch) | |
tree | bed45f50f0a58fddadbef5bd923786107ade4104 /gcc/diagnostic.c | |
parent | fa188ff0f28cb5fe194837825d41dea4e5aa3cdc (diff) | |
download | gcc-cd7fe53b723e8f24dc2efc21bc68a2ac174ee882.tar.gz |
diagnostic.h (diagnostic_classification_change_t): New.
* 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.
From-SVN: r161115
Diffstat (limited to 'gcc/diagnostic.c')
-rw-r--r-- | gcc/diagnostic.c | 91 |
1 files changed, 88 insertions, 3 deletions
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 61401e62a80..34e9679693f 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -306,7 +306,8 @@ default_diagnostic_finalizer (diagnostic_context *context, 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; @@ -316,10 +317,66 @@ diagnostic_classify_diagnostic (diagnostic_context *context, 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 @@ -374,13 +431,41 @@ diagnostic_report_diagnostic (diagnostic_context *context, 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]; } |