This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Remove hardcoded limit on max error message length


Hi!

As shown by the attached testcase, it is trivial to reach gfortran's
max error message length.  I think it would be certainly preferrable
if gfortran switched to diagnostics.c, with some wrappers and fortran
specific argument printer, but that would certainly be much bigger
project than just removing the hardcoded message limit as done in
the patch bellow.
Ok to commit?

2005-07-12  Jakub Jelinek  <jakub@redhat.com>

	* gfortran.h (MAX_ERROR_MESSAGE): Remove.
	(gfc_error_buf): Add allocated and cur_ptr fields.  Change message
	field from array to a pointer.
	* error.c (use_warning_buffer, error_ptr, warning_ptr): Remove.
	(cur_error_buffer): New variable.
	(error_char): Use cur_error_buffer->{message,cur_ptr} instead of
	{warning,error}_{buffer.message,ptr}.  Reallocate message buffer
	if too small.
	(gfc_warning, gfc_notify_std, gfc_error, gfc_error_now): Setup
	cur_error_buffer and its cur_ptr rather than {warning,error}_ptr
	and use_warning_buffer.
	(gfc_warning_check, gfc_error_check): Don't print anything if
	message is NULL.
	(gfc_push_error): Allocate saved message with xstrdup.
	(gfc_pop_error): Free saved message with gfc_free.
	(gfc_free_error): New function.
	* primary.c (match_complex_constant): Call gfc_free_error if
	gfc_pop_error will not be called.
	* match.c (gfc_match_st_function): Likewise.

	* gfortran.dg/g77/cpp6.f: New test.

--- gcc/fortran/gfortran.h.jj	2005-07-07 13:04:21.000000000 +0200
+++ gcc/fortran/gfortran.h	2005-07-12 09:20:42.000000000 +0200
@@ -58,7 +58,6 @@ char *alloca ();
 #define GFC_MAX_LINE 132	/* Characters beyond this are not seen.  */
 #define GFC_MAX_DIMENSIONS 7	/* Maximum dimensions in an array.  */
 #define GFC_LETTERS 26		/* Number of letters in the alphabet.  */
-#define MAX_ERROR_MESSAGE 1000	/* Maximum length of an error message.  */
 
 #define free(x) Use_gfc_free_instead_of_free()
 #define gfc_is_whitespace(c) ((c==' ') || (c=='\t'))
@@ -1548,7 +1547,8 @@ const char * gfc_get_string (const char 
 typedef struct gfc_error_buf
 {
   int flag;
-  char message[MAX_ERROR_MESSAGE];
+  size_t allocated;
+  char *message, *cur_ptr;
 } gfc_error_buf;
 
 void gfc_error_init_1 (void);
@@ -1574,6 +1574,7 @@ try gfc_notify_std (int, const char *, .
 
 void gfc_push_error (gfc_error_buf *);
 void gfc_pop_error (gfc_error_buf *);
+void gfc_free_error (gfc_error_buf *);
 
 void gfc_status (const char *, ...) ATTRIBUTE_PRINTF_1;
 void gfc_status_char (char);
--- gcc/fortran/error.c.jj	2005-07-07 13:04:21.000000000 +0200
+++ gcc/fortran/error.c	2005-07-12 10:00:03.000000000 +0200
@@ -33,12 +33,9 @@ Software Foundation, 51 Franklin Street,
 
 int gfc_suppress_error = 0;
 
-static int terminal_width, buffer_flag, errors,
-  use_warning_buffer, warnings;
+static int terminal_width, buffer_flag, errors, warnings;
 
-static char *error_ptr, *warning_ptr;
-
-static gfc_error_buf error_buffer, warning_buffer;
+static gfc_error_buf error_buffer, warning_buffer, *cur_error_buffer;
 
 
 /* Per-file error initialization.  */
@@ -70,18 +67,19 @@ error_char (char c)
 {
   if (buffer_flag)
     {
-      if (use_warning_buffer)
-	{
-	  *warning_ptr++ = c;
-	  if (warning_ptr - warning_buffer.message >= MAX_ERROR_MESSAGE)
-	    gfc_internal_error ("error_char(): Warning buffer overflow");
-	}
-      else
+      if ((size_t) (cur_error_buffer->cur_ptr - cur_error_buffer->message)
+	  >= cur_error_buffer->allocated)
 	{
-	  *error_ptr++ = c;
-	  if (error_ptr - error_buffer.message >= MAX_ERROR_MESSAGE)
-	    gfc_internal_error ("error_char(): Error buffer overflow");
+	  size_t size = cur_error_buffer->cur_ptr - cur_error_buffer->message;
+	  cur_error_buffer->allocated =
+	    cur_error_buffer->allocated
+	    ? cur_error_buffer->allocated * 2 : 1000;
+	  cur_error_buffer->message
+	    = xrealloc (cur_error_buffer->message,
+			cur_error_buffer->allocated);
+	  cur_error_buffer->cur_ptr = cur_error_buffer->message + size;
 	}
+      *cur_error_buffer->cur_ptr++ = c;
     }
   else
     {
@@ -89,11 +87,16 @@ error_char (char c)
 	{
 	  /* We build up complete lines before handing things
 	     over to the library in order to speed up error printing.  */
-	  static char line[MAX_ERROR_MESSAGE + 1];
-	  static int index = 0;
+	  static char *line;
+	  static size_t allocated = 0, index = 0;
 
+	  if (index + 1 >= allocated)
+	    {
+	      allocated = allocated ? allocated * 2 : 1000;
+	      line = xrealloc (line, allocated);
+	    }
 	  line[index++] = c;
-	  if (c == '\n' || index == MAX_ERROR_MESSAGE)
+	  if (c == '\n')
 	    {
 	      line[index] = '\0';
 	      fputs (line, stderr);
@@ -470,8 +473,8 @@ gfc_warning (const char *format, ...)
     return;
 
   warning_buffer.flag = 1;
-  warning_ptr = warning_buffer.message;
-  use_warning_buffer = 1;
+  warning_buffer.cur_ptr = warning_buffer.message;
+  cur_error_buffer = &warning_buffer;
 
   va_start (argp, format);
   if (buffer_flag == 0)
@@ -506,14 +509,14 @@ gfc_notify_std (int std, const char *for
   if (warning)
     {
       warning_buffer.flag = 1;
-      warning_ptr = warning_buffer.message;
-      use_warning_buffer = 1;
+      warning_buffer.cur_ptr = warning_buffer.message;
+      cur_error_buffer = &warning_buffer;
     }
   else
     {
       error_buffer.flag = 1;
-      error_ptr = error_buffer.message;
-      use_warning_buffer = 0;
+      error_buffer.cur_ptr = error_buffer.message;
+      cur_error_buffer = &error_buffer;
     }
 
   if (buffer_flag == 0)
@@ -577,7 +580,8 @@ gfc_warning_check (void)
   if (warning_buffer.flag)
     {
       warnings++;
-      fputs (warning_buffer.message, stderr);
+      if (warning_buffer.message != NULL)
+	fputs (warning_buffer.message, stderr);
       warning_buffer.flag = 0;
     }
 }
@@ -594,8 +598,8 @@ gfc_error (const char *format, ...)
     return;
 
   error_buffer.flag = 1;
-  error_ptr = error_buffer.message;
-  use_warning_buffer = 0;
+  error_buffer.cur_ptr = error_buffer.message;
+  cur_error_buffer = &error_buffer;
 
   va_start (argp, format);
   if (buffer_flag == 0)
@@ -616,7 +620,8 @@ gfc_error_now (const char *format, ...)
   int i;
 
   error_buffer.flag = 1;
-  error_ptr = error_buffer.message;
+  error_buffer.cur_ptr = error_buffer.message;
+  cur_error_buffer = &error_buffer;
 
   i = buffer_flag;
   buffer_flag = 0;
@@ -691,7 +696,8 @@ gfc_error_check (void)
   if (error_buffer.flag)
     {
       errors++;
-      fputs (error_buffer.message, stderr);
+      if (error_buffer.message != NULL)
+	fputs (error_buffer.message, stderr);
       error_buffer.flag = 0;
     }
 
@@ -706,7 +712,7 @@ gfc_push_error (gfc_error_buf * err)
 {
   err->flag = error_buffer.flag;
   if (error_buffer.flag)
-    strcpy (err->message, error_buffer.message);
+    err->message = xstrdup (error_buffer.message);
 
   error_buffer.flag = 0;
 }
@@ -719,7 +725,22 @@ gfc_pop_error (gfc_error_buf * err)
 {
   error_buffer.flag = err->flag;
   if (error_buffer.flag)
-    strcpy (error_buffer.message, err->message);
+    {
+      size_t len = strlen (err->message) + 1;
+      gcc_assert (len <= error_buffer.allocated);
+      memcpy (error_buffer.message, err->message, len);
+      gfc_free (err->message);
+    }
+}
+
+
+/* Free a pushed error state, but keep the current error state.  */
+
+void
+gfc_free_error (gfc_error_buf * err)
+{
+  if (err->flag)
+    gfc_free (err->message);
 }
 
 
--- gcc/fortran/match.c.jj	2005-07-02 02:28:32.000000000 +0200
+++ gcc/fortran/match.c	2005-07-12 09:21:33.000000000 +0200
@@ -2650,6 +2650,8 @@ gfc_match_st_function (void)
   m = gfc_match (" = %e%t", &expr);
   if (m == MATCH_NO)
     goto undo_error;
+
+  gfc_free_error (&old_error);
   if (m == MATCH_ERROR)
     return m;
 
--- gcc/fortran/primary.c.jj	2005-07-07 17:52:16.000000000 +0200
+++ gcc/fortran/primary.c	2005-07-12 09:22:53.000000000 +0200
@@ -1117,7 +1117,10 @@ match_complex_constant (gfc_expr ** resu
 
   m = match_complex_part (&real);
   if (m == MATCH_NO)
-    goto cleanup;
+    {
+      gfc_free_error (&old_error);
+      goto cleanup;
+    }
 
   if (gfc_match_char (',') == MATCH_NO)
     {
@@ -1132,7 +1135,10 @@ match_complex_constant (gfc_expr ** resu
      sort. These sort of lists are matched prior to coming here.  */
 
   if (m == MATCH_ERROR)
-    goto cleanup;
+    {
+      gfc_free_error (&old_error);
+      goto cleanup;
+    }
   gfc_pop_error (&old_error);
 
   m = match_complex_part (&imag);
--- gcc/testsuite/gfortran.dg/g77/cpp6.f.jj	2005-07-12 09:33:50.000000000 +0200
+++ gcc/testsuite/gfortran.dg/g77/cpp6.f	2005-07-12 09:33:18.000000000 +0200
@@ -0,0 +1,20 @@
+# 1 "test.F"
+# 1 "<built-in>"
+# 1 "<command line>"
+# 1 "test.F"
+	! { dg-do compile }
+
+# 1 "A234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" 1
+
+# 1 "B234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" 1
+
+# 1 "C234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" 1
+
+# 1 "D234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" 1
+	PARAMETER (I=1)
+
+# 2 "C234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" 2
+# 2 "B234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" 2
+# 2 "A234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" 2
+# 3 "test.F" 2
+	END

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]