Hi,
this patch implements the new "#pragma GCC diagnostic off" for the C family of
compilers as well as for the Ada compiler. In fact the subject is slightly
misleading as the main goal of the patch is to wire the diagnostic circuitry
of the Ada front-end to that of the middle-end, thus enabling the former to
drive the latter; but the former has the equivalent of "diagnostic off" so it
needs middle-end support for it, which in turn could be reused by the C family
of compilers.
The implementation in diagnostic.c is a bit kludgy in that it overloads the
option index 0. But this index has been disabled since day #1 and I couldn't
figure out a more elegant approach... Of course I'm ready to implement what
the maintainers would suggest as alternative implementation.
Tested on x86_64-suse-linux, OK for the mainline?
2013-04-19 Eric Botcazou <ebotca...@adacore.com>
* doc/extend.texi (Diagnostic Pragmas): Document diagnostic off.
* diagnostic.c (diagnostic_classify_diagnostic): Accept zero index and
document its semantics.
(diagnostic_report_diagnostic): Adjust accordingly.
c-family/
* c-pragma.c (ALL_KINDS_STRING): Define.
(handle_pragma_diagnostic): Use it and accept diagnostic off.
ada/
* gcc-interface/trans.c: Include diagnostic.h and opts.h.
(Pragma_to_gnu) <Pragma_Warnings>: New case.
* gcc-interface/Make-lang.in (ada/trans.o): Adjust.
2013-04-19 Eric Botcazou <ebotca...@adacore.com>
* gcc.dg/pragma-diag-3.c: New test.
--
Eric Botcazou
Index: doc/extend.texi
===================================================================
--- doc/extend.texi (revision 198047)
+++ doc/extend.texi (working copy)
@@ -14807,6 +14807,10 @@ track of the location of each pragma, an
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 off
+Causes GCC to ignore all the diagnostics. This is equivalent to specifying
+@samp{ignored} for all the diagnostics with the previous form of the pragma.
+
@item #pragma GCC diagnostic push
@itemx #pragma GCC diagnostic pop
Index: c-family/c-pragma.c
===================================================================
--- c-family/c-pragma.c (revision 198047)
+++ c-family/c-pragma.c (working copy)
@@ -684,19 +684,22 @@ handle_pragma_visibility (cpp_reader *du
warning (OPT_Wpragmas, "junk at end of %<#pragma GCC visibility%>");
}
+#define ALL_KINDS_STRING "[error|warning|ignored|off|push|pop]"
+
static void
handle_pragma_diagnostic(cpp_reader *ARG_UNUSED(dummy))
{
- const char *kind_string, *option_string;
+ const char *kind_string;
unsigned int option_index;
enum cpp_ttype token;
diagnostic_t kind;
tree x;
struct cl_option_handlers handlers;
+ bool no_option = false;
token = pragma_lex (&x);
if (token != CPP_NAME)
- GCC_BAD ("missing [error|warning|ignored] after %<#pragma GCC diagnostic%>");
+ GCC_BAD ("missing "ALL_KINDS_STRING" after %<#pragma GCC diagnostic%>");
kind_string = IDENTIFIER_POINTER (x);
if (strcmp (kind_string, "error") == 0)
kind = DK_ERROR;
@@ -704,6 +707,11 @@ handle_pragma_diagnostic(cpp_reader *ARG
kind = DK_WARNING;
else if (strcmp (kind_string, "ignored") == 0)
kind = DK_IGNORED;
+ else if (strcmp (kind_string, "off") == 0)
+ {
+ kind = DK_IGNORED;
+ no_option = true;
+ }
else if (strcmp (kind_string, "push") == 0)
{
diagnostic_push_diagnostics (global_dc, input_location);
@@ -715,23 +723,27 @@ handle_pragma_diagnostic(cpp_reader *ARG
return;
}
else
- GCC_BAD ("expected [error|warning|ignored|push|pop] after %<#pragma GCC diagnostic%>");
+ GCC_BAD ("expected "ALL_KINDS_STRING" after %<#pragma GCC diagnostic%>");
+
+ if (no_option)
+ option_index = 0;
+ else
+ {
+ token = pragma_lex (&x);
+ if (token != CPP_STRING)
+ GCC_BAD ("missing option after %<#pragma GCC diagnostic%> kind");
+ const char *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)
+ break;
+ if (option_index == cl_options_count)
+ GCC_BAD ("unknown option after %<#pragma GCC diagnostic%> kind");
+ }
- token = pragma_lex (&x);
- if (token != CPP_STRING)
- GCC_BAD ("missing option after %<#pragma GCC diagnostic%> kind");
- option_string = TREE_STRING_POINTER (x);
set_default_handlers (&handlers);
- for (option_index = 0; option_index < cl_options_count; option_index++)
- if (strcmp (cl_options[option_index].opt_text, option_string) == 0)
- {
- control_warning_option (option_index, (int) kind, kind != DK_IGNORED,
- input_location, c_family_lang_mask, &handlers,
- &global_options, &global_options_set,
- global_dc);
- return;
- }
- GCC_BAD ("unknown option after %<#pragma GCC diagnostic%> kind");
+ control_warning_option (option_index, (int) kind, kind != DK_IGNORED,
+ input_location, c_family_lang_mask, &handlers,
+ &global_options, &global_options_set, global_dc);
}
/* Parse #pragma GCC target (xxx) to set target specific options. */
Index: diagnostic.c
===================================================================
--- diagnostic.c (revision 198047)
+++ diagnostic.c (working copy)
@@ -551,7 +551,8 @@ default_diagnostic_finalizer (diagnostic
/* Interface to specify diagnostic kind overrides. Returns the
previous setting, or DK_UNSPECIFIED if the parameters are out of
- range. */
+ range. If OPTION_INDEX is zero, the new setting is for all the
+ diagnostics. */
diagnostic_t
diagnostic_classify_diagnostic (diagnostic_context *context,
int option_index,
@@ -560,7 +561,7 @@ diagnostic_classify_diagnostic (diagnost
{
diagnostic_t old_kind;
- if (option_index <= 0
+ if (option_index < 0
|| option_index >= context->n_opts
|| new_kind >= DK_LAST_DIAGNOSTIC_KIND)
return DK_UNSPECIFIED;
@@ -692,9 +693,8 @@ diagnostic_report_diagnostic (diagnostic
/* 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 --)
+ for (int i = context->n_classification_history - 1; i >= 0; i --)
{
if (linemap_location_before_p
(line_table,
@@ -706,7 +706,9 @@ diagnostic_report_diagnostic (diagnostic
i = context->classification_history[i].option;
continue;
}
- if (context->classification_history[i].option == diagnostic->option_index)
+ int option = context->classification_history[i].option;
+ /* The option 0 is for all the diagnostics. */
+ if (option == 0 || option == diagnostic->option_index)
{
diag_class = context->classification_history[i].kind;
if (diag_class != DK_UNSPECIFIED)
Index: testsuite/gcc.dg/pragma-diag-3.c
===================================================================
--- testsuite/gcc.dg/pragma-diag-3.c (revision 0)
+++ testsuite/gcc.dg/pragma-diag-3.c (revision 0)
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized" } */
+
+#pragma GCC diagnostic push
+
+int foo1 (void)
+{
+ int i;
+#pragma GCC diagnostic off
+ return i; /* { dg-bogus "is used uninitialized" } */
+}
+
+#pragma GCC diagnostic pop
+
+int foo2 (void)
+{
+ int i;
+ return i; /* { dg-warning "is used uninitialized" } */
+}
Index: ada/gcc-interface/trans.c
===================================================================
--- ada/gcc-interface/trans.c (revision 198047)
+++ ada/gcc-interface/trans.c (working copy)
@@ -36,6 +36,8 @@
#include "gimple.h"
#include "bitmap.h"
#include "cgraph.h"
+#include "diagnostic.h"
+#include "opts.h"
#include "target.h"
#include "common/common-target.h"
@@ -1184,8 +1186,8 @@ Identifier_to_gnu (Node_Id gnat_node, tr
static tree
Pragma_to_gnu (Node_Id gnat_node)
{
- Node_Id gnat_temp;
tree gnu_result = alloc_stmt_list ();
+ Node_Id gnat_temp;
/* Check for (and ignore) unrecognized pragma and do nothing if we are just
annotating types. */
@@ -1278,6 +1280,89 @@ Pragma_to_gnu (Node_Id gnat_node)
if (write_symbols == NO_DEBUG)
post_error ("must specify -g?", gnat_node);
break;
+
+ case Pragma_Warnings:
+ {
+ Node_Id gnat_expr;
+ /* Preserve the location of the pragma. */
+ const location_t location = input_location;
+ struct cl_option_handlers handlers;
+ unsigned int option_index;
+ diagnostic_t kind;
+ bool imply;
+
+ gnat_temp = First (Pragma_Argument_Associations (gnat_node));
+
+ /* This is the String form: pragma Warnings (String). */
+ if (Nkind (Expression (gnat_temp)) == N_String_Literal)
+ {
+ kind = DK_WARNING;
+ gnat_expr = Expression (gnat_temp);
+ imply = true;
+ }
+
+ /* This is the On/Off form: pragma Warnings (On | Off [,String]). */
+ else if (Nkind (Expression (gnat_temp)) == N_Identifier)
+ {
+ switch (Chars (Expression (gnat_temp)))
+ {
+ case Name_Off:
+ kind = DK_IGNORED;
+ break;
+
+ case Name_On:
+ kind = DK_WARNING;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ if (Present (Next (gnat_temp)))
+ {
+ /* pragma Warnings (On | Off, Name) is handled differently. */
+ if (Nkind (Expression (Next (gnat_temp))) != N_String_Literal)
+ break;
+
+ gnat_expr = Expression (Next (gnat_temp));
+ }
+ else
+ gnat_expr = Empty;
+
+ imply = false;
+ }
+
+ else
+ gcc_unreachable ();
+
+ /* This is the same implementation as in the C family of compilers. */
+ if (Present (gnat_expr))
+ {
+ tree gnu_expr = gnat_to_gnu (gnat_expr);
+ const char *opt_string = TREE_STRING_POINTER (gnu_expr);
+ const int len = TREE_STRING_LENGTH (gnu_expr);
+ if (len < 3 || opt_string[0] != '-' || opt_string[1] != 'W')
+ break;
+ for (option_index = 0;
+ option_index < cl_options_count;
+ option_index++)
+ if (strcmp (cl_options[option_index].opt_text, opt_string) == 0)
+ break;
+ if (option_index == cl_options_count)
+ {
+ post_error ("unknown -W switch", gnat_node);
+ break;
+ }
+ }
+ else
+ option_index = 0;
+
+ set_default_handlers (&handlers);
+ control_warning_option (option_index, (int) kind, imply, location,
+ CL_Ada, &handlers, &global_options,
+ &global_options_set, global_dc);
+ }
+ break;
}
return gnu_result;