diff options
author | Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> | 2007-11-17 17:49:45 +0000 |
---|---|---|
committer | François-Xavier Coudert <fxcoudert@gcc.gnu.org> | 2007-11-17 17:49:45 +0000 |
commit | 2b77e908124cefa480e1e3143c57b4fc3e353da0 (patch) | |
tree | 267c805c4f889eb005138028072b31606dfc71d5 /gcc | |
parent | a0857153ddb27ba0f64a16c934734421fd2fccfc (diff) | |
download | gcc-2b77e908124cefa480e1e3143c57b4fc3e353da0.zip gcc-2b77e908124cefa480e1e3143c57b4fc3e353da0.tar.gz gcc-2b77e908124cefa480e1e3143c57b4fc3e353da0.tar.bz2 |
re PR fortran/25252 (ICE on invalid code)
PR fortran/25252
* interface.c (gfc_current_interface_head,
gfc_set_current_interface_head): New functions.
* decl.c (gfc_match_modproc): Move check for syntax error earlier.
On syntax error, restore previous state of the interface.
* gfortran.h (gfc_current_interface_head,
gfc_set_current_interface_head): New prototypes.
* gfortran.dg/interface_22.f90: New test.
From-SVN: r130259
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/fortran/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/fortran/decl.c | 33 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 2 | ||||
-rw-r--r-- | gcc/fortran/interface.c | 46 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/interface_22.f90 | 25 |
6 files changed, 123 insertions, 3 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index ad4a9f9..4ed0421 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,5 +1,15 @@ 2007-11-17 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + PR fortran/25252 + * interface.c (gfc_current_interface_head, + gfc_set_current_interface_head): New functions. + * decl.c (gfc_match_modproc): Move check for syntax error earlier. + On syntax error, restore previous state of the interface. + * gfortran.h (gfc_current_interface_head, + gfc_set_current_interface_head): New prototypes. + +2007-11-17 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + PR fortran/30285 * module.c (struct written_common, written_commons): New structure. (compare_written_commons, free_written_common, write_common_0): diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index be197bc..325d012 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -5837,6 +5837,7 @@ gfc_match_modproc (void) gfc_symbol *sym; match m; gfc_namespace *module_ns; + gfc_interface *old_interface_head, *interface; if (gfc_state_stack->state != COMP_INTERFACE || gfc_state_stack->previous == NULL @@ -5856,14 +5857,29 @@ gfc_match_modproc (void) if (module_ns == NULL) return MATCH_ERROR; + /* Store the current state of the interface. We will need it if we + end up with a syntax error and need to recover. */ + old_interface_head = gfc_current_interface_head (); + for (;;) { + bool last = false; + m = gfc_match_name (name); if (m == MATCH_NO) goto syntax; if (m != MATCH_YES) return MATCH_ERROR; + /* Check for syntax error before starting to add symbols to the + current namespace. */ + if (gfc_match_eos () == MATCH_YES) + last = true; + if (!last && gfc_match_char (',') != MATCH_YES) + goto syntax; + + /* Now we're sure the syntax is valid, we process this item + further. */ if (gfc_get_symbol (name, module_ns, &sym)) return MATCH_ERROR; @@ -5877,15 +5893,26 @@ gfc_match_modproc (void) sym->attr.mod_proc = 1; - if (gfc_match_eos () == MATCH_YES) + if (last) break; - if (gfc_match_char (',') != MATCH_YES) - goto syntax; } return MATCH_YES; syntax: + /* Restore the previous state of the interface. */ + interface = gfc_current_interface_head (); + gfc_set_current_interface_head (old_interface_head); + + /* Free the new interfaces. */ + while (interface != old_interface_head) + { + gfc_interface *i = interface->next; + gfc_free (interface); + interface = i; + } + + /* And issue a syntax error. */ gfc_syntax_error (ST_MODULE_PROC); return MATCH_ERROR; } diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 39fd3a1..cc6ad98 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -2308,6 +2308,8 @@ try gfc_extend_expr (gfc_expr *); void gfc_free_formal_arglist (gfc_formal_arglist *); try gfc_extend_assign (gfc_code *, gfc_namespace *); try gfc_add_interface (gfc_symbol *); +gfc_interface *gfc_current_interface_head (void); +void gfc_set_current_interface_head (gfc_interface *); /* io.c */ extern gfc_st_label format_asterisk; diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c index 650cd21..67a60f6 100644 --- a/gcc/fortran/interface.c +++ b/gcc/fortran/interface.c @@ -2707,6 +2707,52 @@ gfc_add_interface (gfc_symbol *new) } +gfc_interface * +gfc_current_interface_head (void) +{ + switch (current_interface.type) + { + case INTERFACE_INTRINSIC_OP: + return current_interface.ns->operator[current_interface.op]; + break; + + case INTERFACE_GENERIC: + return current_interface.sym->generic; + break; + + case INTERFACE_USER_OP: + return current_interface.uop->operator; + break; + + default: + gcc_unreachable (); + } +} + + +void +gfc_set_current_interface_head (gfc_interface *i) +{ + switch (current_interface.type) + { + case INTERFACE_INTRINSIC_OP: + current_interface.ns->operator[current_interface.op] = i; + break; + + case INTERFACE_GENERIC: + current_interface.sym->generic = i; + break; + + case INTERFACE_USER_OP: + current_interface.uop->operator = i; + break; + + default: + gcc_unreachable (); + } +} + + /* Gets rid of a formal argument list. We do not free symbols. Symbols are freed when a namespace is freed. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1386ceb..8fce122 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2007-11-17 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR fortran/25252 + * interface.c (gfc_current_interface_head, + gfc_set_current_interface_head): New functions. + * decl.c (gfc_match_modproc): Move check for syntax error earlier. + On syntax error, restore previous state of the interface. + * gfortran.h (gfc_current_interface_head, + gfc_set_current_interface_head): New prototypes. + 2007-11-17 Richard Guenther <rguenther@suse.de> PR middle-end/34130 diff --git a/gcc/testsuite/gfortran.dg/interface_22.f90 b/gcc/testsuite/gfortran.dg/interface_22.f90 new file mode 100644 index 0000000..6228fc9 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/interface_22.f90 @@ -0,0 +1,25 @@ +! { dg-do compile } +! +! This is a check for error recovery: we used to ICE in various places, or +! emit bogus error messages (PR 25252) +! +module foo + interface bar + module procedure X, Y, ! { dg-error "Syntax error in MODULE PROCEDURE statement" } + end interface bar +end module + +module g + interface i + module procedure sint => sreal ! { dg-error "Syntax error in MODULE PROCEDURE statement" } + end interface i +end module g + +module gswap + type points + real :: x, y + end type points + interface swap + module procedure sreal, schar, sint => sreal ! { dg-error "Syntax error in MODULE PROCEDURE statement" } + end interface swap +end module gswap |