Index: gcc/pretty-print.c
===================================================================
--- gcc/pretty-print.c	(revision 218090)
+++ gcc/pretty-print.c	(working copy)
@@ -40,7 +40,8 @@
     cur_chunk_array (),
     stream (stderr),
     line_length (),
-    digit_buffer ()
+    digit_buffer (),
+    flush_p (true)
 {
   obstack_init (&formatted_obstack);
   obstack_init (&chunk_obstack);
@@ -679,12 +680,25 @@
   pp_wrapping_mode (pp) = oldmode;
 }
 
-/* Flush the content of BUFFER onto the attached stream.  */
+/* Flush the content of BUFFER onto the attached stream.  This
+   function does nothing unless pp->output_buffer->flush_p.  */
 void
 pp_flush (pretty_printer *pp)
 {
+  pp_clear_state (pp);
+  if (!pp->buffer->flush_p)
+    return;
   pp_write_text_to_stream (pp);
+  fflush (pp_buffer (pp)->stream);
+}
+
+/* Flush the content of BUFFER onto the attached stream independently
+   of the value of pp->output_buffer->flush_p.  */
+void
+pp_really_flush (pretty_printer *pp)
+{
   pp_clear_state (pp);
+  pp_write_text_to_stream (pp);
   fflush (pp_buffer (pp)->stream);
 }
 
Index: gcc/pretty-print.h
===================================================================
--- gcc/pretty-print.h	(revision 218090)
+++ gcc/pretty-print.h	(working copy)
@@ -100,6 +100,11 @@
   /* This must be large enough to hold any printed integer or
      floating-point value.  */
   char digit_buffer[128];
+
+  /* Nonzero means that text should be flushed when
+     appropriate. Otherwise, text is buffered until either
+     pp_pp_really_flush or pp_clear_output_area are called. */
+  bool flush_p;
 };
 
 /* The type of pretty-printer flags passed to clients.  */
@@ -314,6 +319,7 @@
 extern void pp_verbatim (pretty_printer *, const char *, ...)
      ATTRIBUTE_GCC_PPDIAG(2,3);
 extern void pp_flush (pretty_printer *);
+extern void pp_really_flush (pretty_printer *);
 extern void pp_format (pretty_printer *, text_info *);
 extern void pp_output_formatted_text (pretty_printer *);
 extern void pp_format_verbatim (pretty_printer *, text_info *);
Index: gcc/fortran/gfortran.h
===================================================================
--- gcc/fortran/gfortran.h	(revision 218090)
+++ gcc/fortran/gfortran.h	(working copy)
@@ -2443,7 +2443,6 @@
   int dump_fortran_optimized;
 
   int warn_aliasing;
-  int warn_ampersand;
   int warn_function_elimination;
   int warn_implicit_interface;
   int warn_implicit_procedure;
@@ -2691,6 +2690,7 @@
 const char *gfc_print_wide_char (gfc_char_t);
 
 void gfc_warning (const char *, ...) ATTRIBUTE_GCC_GFC(1,2);
+bool gfc_warning_1 (int opt, const char *, ...) ATTRIBUTE_GCC_GFC(2,3);
 void gfc_warning_now_1 (const char *, ...) ATTRIBUTE_GCC_GFC(1,2);
 bool gfc_warning_now (const char *, ...) ATTRIBUTE_GCC_GFC(1,2);
 bool gfc_warning_now (int opt, const char *, ...) ATTRIBUTE_GCC_GFC(2,3);
@@ -2719,7 +2719,7 @@
 void gfc_free_error (gfc_error_buf *);
 
 void gfc_get_errors (int *, int *);
-void gfc_errors_to_warnings (int);
+void gfc_errors_to_warnings (bool);
 
 /* arith.c */
 void gfc_arith_init_1 (void);
Index: gcc/fortran/error.c
===================================================================
--- gcc/fortran/error.c	(revision 218090)
+++ gcc/fortran/error.c	(working copy)
@@ -50,7 +50,11 @@
 
 static gfc_error_buf error_buffer, warning_buffer, *cur_error_buffer;
 
+static output_buffer pp_warning_buffer;
+static int warningcount_buffered, werrorcount_buffered;
 
+#include <new> /* For placement-new */
+
 /* Go one level deeper suppressing errors.  */
 
 void
@@ -122,6 +126,7 @@
 gfc_buffer_error (int flag)
 {
   buffer_flag = flag;
+  pp_warning_buffer.flush_p = !flag;
 }
 
 
@@ -833,6 +838,52 @@
 }
 
 
+/* Issue a warning.  */
+
+bool
+gfc_warning_1 (int opt, const char *gmsgid, ...)
+{
+  va_list argp;
+  diagnostic_info diagnostic;
+  bool ret;
+  bool fatal_errors = global_dc->fatal_errors;
+  pretty_printer *pp = global_dc->printer;
+  output_buffer *tmp_buffer = pp->buffer;
+  int warningcount_saved = 0;
+  int werrorcount_saved = 0;
+
+  if (!pp_warning_buffer.flush_p)
+    {
+      warningcount_saved = warningcount;
+      werrorcount_saved = werrorcount;
+      /* To prevent -fmax-errors= triggering.  */
+      werrorcount--;
+      pp->buffer = &pp_warning_buffer;
+      global_dc->fatal_errors = false;
+    }
+
+  va_start (argp, gmsgid);
+  diagnostic_set_info (&diagnostic, gmsgid, &argp, UNKNOWN_LOCATION,
+		       DK_WARNING);
+  diagnostic.option_index = opt;
+  ret = report_diagnostic (&diagnostic);
+
+  if (!pp_warning_buffer.flush_p)
+    {
+      warningcount_buffered = warningcount - warningcount_saved;
+      warningcount = warningcount_saved;
+      werrorcount++; /* Undo the above werrorcount-- */
+      werrorcount_buffered = werrorcount - werrorcount_saved;
+      werrorcount = werrorcount_saved;
+
+      pp->buffer = tmp_buffer;
+      global_dc->fatal_errors = fatal_errors;
+    }
+  
+  va_end (argp);
+  return ret;
+}
+
 /* Whether, for a feature included in a given standard set (GFC_STD_*),
    we should issue an error or a warning, or be quiet.  */
 
@@ -1176,6 +1227,15 @@
 gfc_clear_warning (void)
 {
   warning_buffer.flag = 0;
+  
+  pretty_printer *pp = global_dc->printer;
+  output_buffer *tmp_buffer = pp->buffer;
+  pp->buffer = &pp_warning_buffer;
+  pp_clear_output_area (pp);
+  pp->buffer = tmp_buffer;
+  pp_warning_buffer.flush_p = false;
+  warningcount_buffered = 0;
+  werrorcount_buffered = 0;
 }
 
 
@@ -1192,6 +1252,20 @@
 	fputs (warning_buffer.message, stderr);
       warning_buffer.flag = 0;
     }
+
+  /* This is for the new diagnostics machinery.  */
+  pretty_printer *pp = global_dc->printer;
+  output_buffer *tmp_buffer = pp->buffer;
+  pp->buffer = &pp_warning_buffer;
+  if (pp_last_position_in_text (pp) != NULL)
+    {
+      pp_really_flush (pp);
+      pp_warning_buffer.flush_p = true;
+      warningcount += warningcount_buffered;
+      werrorcount += werrorcount_buffered;
+    }
+
+  pp->buffer = tmp_buffer;
 }
 
 
@@ -1395,9 +1469,9 @@
 /* Switch errors into warnings.  */
 
 void
-gfc_errors_to_warnings (int f)
+gfc_errors_to_warnings (bool f)
 {
-  warnings_not_errors = (f == 1) ? 1 : 0;
+  warnings_not_errors = f;
 }
 
 void
@@ -1407,6 +1481,7 @@
   diagnostic_finalizer (global_dc) = gfc_diagnostic_finalizer;
   diagnostic_format_decoder (global_dc) = gfc_format_decoder;
   global_dc->caret_char = '^';
+  new (&pp_warning_buffer) output_buffer ();
 }
 
 void
Index: gcc/fortran/lang.opt
===================================================================
--- gcc/fortran/lang.opt	(revision 218090)
+++ gcc/fortran/lang.opt	(working copy)
@@ -202,9 +202,13 @@
 Warn about alignment of COMMON blocks
 
 Wampersand
-Fortran Warning
+Fortran Warning Var(warn_ampersand) LangEnabledBy(Fortran, Wpedantic)
 Warn about missing ampersand in continued character constants
 
+Wampersand
+LangEnabledBy(Fortran, Wall)
+;
+
 Warray-temporaries
 Fortran Warning
 Warn about creation of array temporaries
Index: gcc/fortran/scanner.c
===================================================================
--- gcc/fortran/scanner.c	(revision 218090)
+++ gcc/fortran/scanner.c	(working copy)
@@ -1154,9 +1154,10 @@
 	  if (in_string)
 	    {
 	      gfc_current_locus.nextc--;
-	      if (gfc_option.warn_ampersand && in_string == INSTRING_WARN)
-		gfc_warning ("Missing '&' in continued character "
-			     "constant at %C");
+	      if (warn_ampersand && in_string == INSTRING_WARN)
+		gfc_warning_1 (OPT_Wampersand,
+			       "Missing %<&%> in continued character "
+			       "constant at %C");
 	    }
 	  /* Both !$omp and !$ -fopenmp continuation lines have & on the
 	     continuation line only optionally.  */
Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c	(revision 218090)
+++ gcc/fortran/resolve.c	(working copy)
@@ -2431,7 +2431,7 @@
 
       if (!pedantic && (gfc_option.allow_std & GFC_STD_GNU))
 	/* Turn erros into warnings with -std=gnu and -std=legacy.  */
-	gfc_errors_to_warnings (1);
+	gfc_errors_to_warnings (true);
 
       if (!gfc_compare_interfaces (sym, def_sym, sym->name, 0, 1,
 				   reason, sizeof(reason), NULL, NULL))
@@ -2444,14 +2444,14 @@
       if (!pedantic
 	  || ((gfc_option.warn_std & GFC_STD_LEGACY)
 	      && !(gfc_option.warn_std & GFC_STD_GNU)))
-	gfc_errors_to_warnings (1);
+	gfc_errors_to_warnings (true);
 
       if (sym->attr.if_source != IFSRC_IFBODY)
 	gfc_procedure_use (def_sym, actual, where);
     }
 
 done:
-  gfc_errors_to_warnings (0);
+  gfc_errors_to_warnings (false);
 
   if (gsym->type == GSYM_UNKNOWN)
     {
Index: gcc/fortran/primary.c
===================================================================
--- gcc/fortran/primary.c	(revision 218090)
+++ gcc/fortran/primary.c	(working copy)
@@ -951,7 +951,7 @@
 match_string_constant (gfc_expr **result)
 {
   char name[GFC_MAX_SYMBOL_LEN + 1], peek;
-  int i, kind, length, warn_ampersand, ret;
+  int i, kind, length, warn_ampersand_saved, ret;
   locus old_locus, start_locus;
   gfc_symbol *sym;
   gfc_expr *e;
@@ -1071,8 +1071,8 @@
 
   /* We disable the warning for the following loop as the warning has already
      been printed in the loop above.  */
-  warn_ampersand = gfc_option.warn_ampersand;
-  gfc_option.warn_ampersand = 0;
+  warn_ampersand_saved = warn_ampersand;
+  warn_ampersand = false;
 
   p = e->value.character.string;
   for (i = 0; i < length; i++)
@@ -1091,7 +1091,7 @@
     }
 
   *p = '\0';	/* TODO: C-style string is for development/debug purposes.  */
-  gfc_option.warn_ampersand = warn_ampersand;
+  warn_ampersand = warn_ampersand_saved;
 
   next_string_char (delimiter, &ret);
   if (ret != -1)
Index: gcc/fortran/options.c
===================================================================
--- gcc/fortran/options.c	(revision 218090)
+++ gcc/fortran/options.c	(working copy)
@@ -94,7 +94,6 @@
   gfc_option.dump_fortran_optimized = 0;
 
   gfc_option.warn_aliasing = 0;
-  gfc_option.warn_ampersand = 0;
   gfc_option.warn_array_temp = 0;
   gfc_option.warn_function_elimination = 0;
   gfc_option.warn_implicit_interface = 0;
@@ -423,9 +422,6 @@
   if (!gfc_option.flag_automatic)
     gfc_option.flag_max_stack_var_size = 0;
   
-  if (pedantic)
-    gfc_option.warn_ampersand = 1;
-
   /* Optimization implies front end optimization, unless the user
      specified it directly.  */
 
@@ -447,7 +443,6 @@
 set_Wall (int setting)
 {
   gfc_option.warn_aliasing = setting;
-  gfc_option.warn_ampersand = setting;
   gfc_option.warn_line_truncation = setting;
   gfc_option.warn_surprising = setting;
   gfc_option.warn_underflow = setting;
@@ -642,10 +637,6 @@
       gfc_option.warn_aliasing = value;
       break;
 
-    case OPT_Wampersand:
-      gfc_option.warn_ampersand = value;
-      break;
-
     case OPT_Warray_temporaries:
       gfc_option.warn_array_temp = value;
       break;
@@ -1003,7 +994,7 @@
       gfc_option.max_continue_fixed = 19;
       gfc_option.max_continue_free = 39;
       gfc_option.max_identifier_length = 31;
-      gfc_option.warn_ampersand = 1;
+      warn_ampersand = 1;
       warn_tabs = 1;
       break;
 
@@ -1012,7 +1003,7 @@
 	| GFC_STD_F2003 | GFC_STD_F95 | GFC_STD_F2008_OBS;
       gfc_option.warn_std = GFC_STD_F95_OBS;
       gfc_option.max_identifier_length = 63;
-      gfc_option.warn_ampersand = 1;
+      warn_ampersand = 1;
       warn_tabs = 1;
       break;
 
@@ -1021,7 +1012,7 @@
 	| GFC_STD_F2003 | GFC_STD_F95 | GFC_STD_F2008 | GFC_STD_F2008_OBS;
       gfc_option.warn_std = GFC_STD_F95_OBS | GFC_STD_F2008_OBS;
       gfc_option.max_identifier_length = 63;
-      gfc_option.warn_ampersand = 1;
+      warn_ampersand = 1;
       warn_tabs = 1;
       break;
 
@@ -1031,7 +1022,7 @@
 	| GFC_STD_F2008_TS;
       gfc_option.warn_std = GFC_STD_F95_OBS | GFC_STD_F2008_OBS;
       gfc_option.max_identifier_length = 63;
-      gfc_option.warn_ampersand = 1;
+      warn_ampersand = 1;
       warn_tabs = 1;
       break;
 
