summaryrefslogtreecommitdiff
path: root/gcc/fortran/error.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/error.c')
-rw-r--r--gcc/fortran/error.c124
1 files changed, 123 insertions, 1 deletions
diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c
index 70429d3e122..d6475f37248 100644
--- a/gcc/fortran/error.c
+++ b/gcc/fortran/error.c
@@ -50,6 +50,10 @@ static int terminal_width, buffer_flag, errors, warnings;
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. */
@@ -122,6 +126,7 @@ void
gfc_buffer_error (int flag)
{
buffer_flag = flag;
+ pp_warning_buffer.flush_p = !flag;
}
@@ -804,10 +809,25 @@ gfc_increment_error_count (void)
}
+/* Clear any output buffered in a pretty-print output_buffer. */
+
+static void
+gfc_clear_pp_buffer (output_buffer *this_buffer)
+{
+ pretty_printer *pp = global_dc->printer;
+ output_buffer *tmp_buffer = pp->buffer;
+ pp->buffer = this_buffer;
+ pp_clear_output_area (pp);
+ pp->buffer = tmp_buffer;
+}
+
+
/* Issue a warning. */
+/* Use gfc_warning instead, unless two locations are used in the same
+ warning or for scanner.c, if the location is not properly set up. */
void
-gfc_warning (const char *gmsgid, ...)
+gfc_warning_1 (const char *gmsgid, ...)
{
va_list argp;
@@ -833,6 +853,88 @@ gfc_warning (const char *gmsgid, ...)
}
+/* This is just a helper function to avoid duplicating the logic of
+ gfc_warning. */
+
+static bool
+gfc_warning (int opt, const char *gmsgid, va_list ap) ATTRIBUTE_GCC_GFC(2,0);
+
+static bool
+gfc_warning (int opt, const char *gmsgid, va_list ap)
+{
+ va_list argp;
+ va_copy (argp, ap);
+
+ diagnostic_info diagnostic;
+ bool fatal_errors = global_dc->fatal_errors;
+ pretty_printer *pp = global_dc->printer;
+ output_buffer *tmp_buffer = pp->buffer;
+ bool buffered_p = !pp_warning_buffer.flush_p;
+
+ gfc_clear_pp_buffer (&pp_warning_buffer);
+
+ if (buffered_p)
+ {
+ pp->buffer = &pp_warning_buffer;
+ global_dc->fatal_errors = false;
+ /* To prevent -fmax-errors= triggering. */
+ --werrorcount;
+ }
+
+ diagnostic_set_info (&diagnostic, gmsgid, &argp, UNKNOWN_LOCATION,
+ DK_WARNING);
+ diagnostic.option_index = opt;
+ bool ret = report_diagnostic (&diagnostic);
+
+ if (buffered_p)
+ {
+ pp->buffer = tmp_buffer;
+ global_dc->fatal_errors = fatal_errors;
+
+ warningcount_buffered = 0;
+ werrorcount_buffered = 0;
+ /* Undo the above --werrorcount if not Werror, otherwise
+ werrorcount is correct already. */
+ if (!ret)
+ ++werrorcount;
+ else if (diagnostic.kind == DK_ERROR)
+ ++werrorcount_buffered;
+ else
+ ++werrorcount, --warningcount, ++warningcount_buffered;
+ }
+
+ va_end (argp);
+ return ret;
+}
+
+/* Issue a warning. */
+/* This function uses the common diagnostics, but does not support
+ two locations; when being used in scanner.c, ensure that the location
+ is properly setup. Otherwise, use gfc_warning_1. */
+
+bool
+gfc_warning (int opt, const char *gmsgid, ...)
+{
+ va_list argp;
+
+ va_start (argp, gmsgid);
+ bool ret = gfc_warning (opt, gmsgid, argp);
+ va_end (argp);
+ return ret;
+}
+
+bool
+gfc_warning (const char *gmsgid, ...)
+{
+ va_list argp;
+
+ va_start (argp, gmsgid);
+ bool ret = gfc_warning (0, gmsgid, argp);
+ 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 +1278,11 @@ void
gfc_clear_warning (void)
{
warning_buffer.flag = 0;
+
+ gfc_clear_pp_buffer (&pp_warning_buffer);
+ warningcount_buffered = 0;
+ werrorcount_buffered = 0;
+ pp_warning_buffer.flush_p = false;
}
@@ -1192,6 +1299,20 @@ gfc_warning_check (void)
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;
}
@@ -1407,6 +1528,7 @@ gfc_diagnostics_init (void)
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