diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 5f17e5edc6b..8fd316abb0f 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,5 +1,25 @@ 2005-07-14 Jakub Jelinek + * gfortran.h (MAX_ERROR_MESSAGE): Remove. + (gfc_error_buf): Add allocated and index 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,index} 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 index 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. + PR fortran/22417 * scanner.c (preprocessor_line): Don't treat flag 3 as the start of a new file. Fix file left but not entered warning. diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c index fe7decc5dfb..009419a0979 100644 --- a/gcc/fortran/error.c +++ b/gcc/fortran/error.c @@ -33,12 +33,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 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,16 @@ error_char (char c) { if (buffer_flag) { - if (use_warning_buffer) + if (cur_error_buffer->index >= cur_error_buffer->allocated) { - *warning_ptr++ = c; - if (warning_ptr - warning_buffer.message >= MAX_ERROR_MESSAGE) - gfc_internal_error ("error_char(): Warning buffer overflow"); - } - else - { - *error_ptr++ = c; - if (error_ptr - error_buffer.message >= MAX_ERROR_MESSAGE) - gfc_internal_error ("error_char(): Error buffer overflow"); + 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->message[cur_error_buffer->index++] = c; } else { @@ -89,11 +84,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 +470,8 @@ gfc_warning (const char *format, ...) return; warning_buffer.flag = 1; - warning_ptr = warning_buffer.message; - use_warning_buffer = 1; + warning_buffer.index = 0; + cur_error_buffer = &warning_buffer; va_start (argp, format); if (buffer_flag == 0) @@ -503,18 +503,9 @@ gfc_notify_std (int std, const char *format, ...) if (gfc_suppress_error) return warning ? SUCCESS : FAILURE; - if (warning) - { - warning_buffer.flag = 1; - warning_ptr = warning_buffer.message; - use_warning_buffer = 1; - } - else - { - error_buffer.flag = 1; - error_ptr = error_buffer.message; - use_warning_buffer = 0; - } + cur_error_buffer = warning ? &warning_buffer : &error_buffer; + cur_error_buffer->flag = 1; + cur_error_buffer->index = 0; if (buffer_flag == 0) { @@ -577,7 +568,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 +586,8 @@ gfc_error (const char *format, ...) return; error_buffer.flag = 1; - error_ptr = error_buffer.message; - use_warning_buffer = 0; + error_buffer.index = 0; + cur_error_buffer = &error_buffer; va_start (argp, format); if (buffer_flag == 0) @@ -616,7 +608,8 @@ gfc_error_now (const char *format, ...) int i; error_buffer.flag = 1; - error_ptr = error_buffer.message; + error_buffer.index = 0; + cur_error_buffer = &error_buffer; i = buffer_flag; buffer_flag = 0; @@ -691,7 +684,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 +700,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 +713,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); } diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 71b6c19b932..dea08c3e20d 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -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 *, ...) ATTRIBUTE_PRINTF_1; typedef struct gfc_error_buf { int flag; - char message[MAX_ERROR_MESSAGE]; + size_t allocated, index; + char *message; } gfc_error_buf; void gfc_error_init_1 (void); @@ -1574,6 +1574,7 @@ try gfc_notify_std (int, const char *, ...) ATTRIBUTE_GCC_GFC(2,3); 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); diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c index f63eaf6bed3..7f249eecf10 100644 --- a/gcc/fortran/match.c +++ b/gcc/fortran/match.c @@ -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; diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c index 36e5eb96f37..888caffa5c2 100644 --- a/gcc/fortran/primary.c +++ b/gcc/fortran/primary.c @@ -1117,7 +1117,10 @@ match_complex_constant (gfc_expr ** result) 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 ** result) 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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d0c2c653efa..334e96e4638 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,7 @@ 2005-07-14 Jakub Jelinek + * gfortran.dg/g77/cpp6.f: New test. + PR fortran/22417 * gfortran.dg/g77/cpp5.F: New test. * gfortran.dg/g77/cpp5.h: New file. diff --git a/gcc/testsuite/gfortran.dg/g77/cpp6.f b/gcc/testsuite/gfortran.dg/g77/cpp6.f new file mode 100644 index 00000000000..5f973c15b2b --- /dev/null +++ b/gcc/testsuite/gfortran.dg/g77/cpp6.f @@ -0,0 +1,20 @@ +# 1 "test.F" +# 1 "" +# 1 "" +# 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