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;
