diff options
author | Mikael Morin <mikael@gcc.gnu.org> | 2023-08-30 14:18:56 +0200 |
---|---|---|
committer | Mikael Morin <mikael@gcc.gnu.org> | 2023-08-30 14:20:05 +0200 |
commit | d58150452976c4ca65ddc811fac78ef956fa96b0 (patch) | |
tree | 416ad179572be1fe7560d2625dbf2428c031fdb9 /gcc/testsuite | |
parent | caa7a99a052929d5970677c5b639e1fa5166e334 (diff) | |
download | gcc-d58150452976c4ca65ddc811fac78ef956fa96b0.zip gcc-d58150452976c4ca65ddc811fac78ef956fa96b0.tar.gz gcc-d58150452976c4ca65ddc811fac78ef956fa96b0.tar.bz2 |
fortran: Restore interface to its previous state on error [PR48776]
Keep memory of the content of the current interface body being parsed
and restore it to its previous state if it has been modified at the time
a parse attempt fails.
This fixes memory errors and random segmentation faults caused by
dangling symbol pointers kept in interfaces' linked lists of symbols.
If a parsing attempt fails and symbols are freed, they should also be
removed from the current interface linked list.
As the list of symbol is a linked list, and parsing only adds new
symbols to the head of the list, all that is needed to track the
previous content of the list is a pointer to its previous head.
This adds such a pointer, and the restoration of the list of symbols
to that pointer on error.
PR fortran/48776
gcc/fortran/ChangeLog:
* gfortran.h (gfc_drop_interface_elements_before): New prototype.
(gfc_current_interface_head): Return a reference to the pointer.
* interface.cc (gfc_current_interface_head): Ditto.
(free_interface_elements_until): New function, generalizing
gfc_free_interface.
(gfc_free_interface): Use free_interface_elements_until.
(gfc_drop_interface_elements_before): New function.
* parse.cc
(current_interface_ptr, previous_interface_head): New static variables.
(current_interface_valid_p, get_current_interface_ptr): New functions.
(decode_statement): Initialize previous_interface_head.
(reject_statement): Restore current interface pointer to point to
previous_interface_head.
gcc/testsuite/ChangeLog:
* gfortran.dg/interface_procedure_1.f90: New test.
Diffstat (limited to 'gcc/testsuite')
-rw-r--r-- | gcc/testsuite/gfortran.dg/interface_procedure_1.f90 | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/gcc/testsuite/gfortran.dg/interface_procedure_1.f90 b/gcc/testsuite/gfortran.dg/interface_procedure_1.f90 new file mode 100644 index 0000000..6a58b6a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/interface_procedure_1.f90 @@ -0,0 +1,23 @@ +! { dg-do compile } +! { dg-additional-options "-std=f95" } +! +! PR fortran/48776 +! The following used to generate a segmentation fault in the front-end, +! because a pointer to the get1 symbol was remaining in the get interface +! after the procedure statement was rejected and the symbol freed. + + interface get + procedure get1 ! { dg-error "Fortran 2003: PROCEDURE statement" } + end interface + + integer :: h + call set1 (get (h)) ! { dg-error "no specific function for the generic 'get'" } +contains + subroutine set1 (a) + integer, intent(in) :: a + end subroutine + + integer function get1 (s) + integer :: s + end function +end |