2016-12-02  Nathan Sidwell  <nathan@acm.org>

	gcc/
	* diagnostic.c (diagnostic_check_max_errors): New, broken out of ...
	(diagnostic_action_after_output): ... here.
	(diagnostic_report_diagnostic): Call it for non-notes.
	* diagnostic.h (diagnostic_check_max_errors): Declare.

	gcc/fortran/
	* error.c (gfc_warning_check): Call diagnostic_check_max_errors.
	(gfc_error_check): Likewise.

	gcc/testsuite/
	* c-c++-common/fmax_errors.c: Check notes after last error are
	emitted.

Index: gcc/diagnostic.c
===================================================================
--- gcc/diagnostic.c	(revision 243115)
+++ gcc/diagnostic.c	(working copy)
@@ -446,6 +446,29 @@ bt_err_callback (void *data ATTRIBUTE_UN
 	   errnum == 0 ? "" : xstrerror (errnum));
 }
 
+/* Check if we've met the maximum error limit.  */
+
+void
+diagnostic_check_max_errors (diagnostic_context *context, bool flush)
+{
+  if (!context->max_errors)
+    return;
+
+  int count = (diagnostic_kind_count (context, DK_ERROR)
+	       + diagnostic_kind_count (context, DK_SORRY)
+	       + diagnostic_kind_count (context, DK_WERROR));
+
+  if (count >= (int) context->max_errors)
+    {
+      fnotice (stderr,
+	       "compilation terminated due to -fmax-errors=%u.\n",
+	       context->max_errors);
+      if (flush)
+	diagnostic_finish (context);
+      exit (FATAL_EXIT_CODE);
+    }
+}
+
 /* Take any action which is expected to happen after the diagnostic
    is written out.  This function does not always return.  */
 void
@@ -470,18 +493,6 @@ diagnostic_action_after_output (diagnost
 	  diagnostic_finish (context);
 	  exit (FATAL_EXIT_CODE);
 	}
-      if (context->max_errors != 0
-	  && ((unsigned) (diagnostic_kind_count (context, DK_ERROR)
-			  + diagnostic_kind_count (context, DK_SORRY)
-			  + diagnostic_kind_count (context, DK_WERROR))
-	      >= context->max_errors))
-	{
-	  fnotice (stderr,
-		   "compilation terminated due to -fmax-errors=%u.\n",
-		   context->max_errors);
-	  diagnostic_finish (context);
-	  exit (FATAL_EXIT_CODE);
-	}
       break;
 
     case DK_ICE:
@@ -892,6 +901,9 @@ diagnostic_report_diagnostic (diagnostic
 	return false;
     }
 
+  if (diagnostic->kind != DK_NOTE)
+    diagnostic_check_max_errors (context);
+
   context->lock++;
 
   if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
Index: gcc/diagnostic.h
===================================================================
--- gcc/diagnostic.h	(revision 243115)
+++ gcc/diagnostic.h	(working copy)
@@ -320,6 +320,7 @@ void default_diagnostic_start_span_fn (d
 void default_diagnostic_finalizer (diagnostic_context *, diagnostic_info *);
 void diagnostic_set_caret_max_width (diagnostic_context *context, int value);
 void diagnostic_action_after_output (diagnostic_context *, diagnostic_t);
+void diagnostic_check_max_errors (diagnostic_context *, bool flush = false);
 
 void diagnostic_file_cache_fini (void);
 
Index: gcc/fortran/error.c
===================================================================
--- gcc/fortran/error.c	(revision 243115)
+++ gcc/fortran/error.c	(working copy)
@@ -1226,6 +1226,7 @@ gfc_warning_check (void)
       diagnostic_action_after_output (global_dc,
 				      warningcount_buffered
 				      ? DK_WARNING : DK_ERROR);
+      diagnostic_check_max_errors (global_dc, true);
     }
 }
 
@@ -1370,6 +1371,7 @@ gfc_error_check (void)
       gcc_assert (gfc_output_buffer_empty_p (pp_error_buffer));
       pp->buffer = tmp_buffer;
       diagnostic_action_after_output (global_dc, DK_ERROR);
+      diagnostic_check_max_errors (global_dc, true);
       return true;
     }
 
Index: gcc/testsuite/c-c++-common/fmax-errors.c
===================================================================
--- gcc/testsuite/c-c++-common/fmax-errors.c	(revision 243115)
+++ gcc/testsuite/c-c++-common/fmax-errors.c	(working copy)
@@ -1,11 +1,21 @@
 /* PR c/44782 */
 /* { dg-do compile } */
-/* { dg-options "-fmax-errors=3" } */
+/* { dg-options "-fmax-errors=3 -Wall" } */
 
 void foo (unsigned int i, unsigned int j)
 {
   (i) ();			/* { dg-error "" } */
   (j) ();			/* { dg-error "" } */
-  (i+j) ();			/* { dg-error "" } */
+
+  i + j; /* { dg-warning "" }  */
+
+  (k) ();			/* { dg-error "" } */
+  /* Make sure we see the notes related to the final error we emit.  */
+  /* { dg-message "identifier" "" { target c } 12 } */
+
+  /* Warnings after the final error should not appear.  */
+  i + j; /* no warning.  */
+
   (i*j) ();			/* no error here due to -fmax-errors */
+
 } /* { dg-prune-output "compilation terminated" } */
