fortran: Avoid infinite self-recursion [PR105381]

Dummy array decls are local decls different from the argument decl
accessible through GFC_DECL_SAVED_DESCRIPTOR.  If the argument decl has
a DECL_LANG_SPECIFIC set, it is copied over to the local decl at the
time the latter is created, so that the DECL_LANG_SPECIFIC object is
shared between local dummy decl and argument decl, and thus the
GFC_DECL_SAVED_DESCRIPTOR of the argument decl is the argument decl
itself.

The r12-8230-g7964ab6c364c410c34efe7ca2eba797d36525349 change introduced
the non_negative_strides_array_p predicate which recurses through
GFC_DECL_SAVED_DESCRIPTOR to avoid seeing dummy decls as purely local
decls.  As the GFC_DECL_SAVED_DESCRIPTOR of the argument decl is itself,
this can cause infinite recursion.

This change adds a check to avoid infinite recursion.

	PR fortran/102043
	PR fortran/105381

gcc/fortran/ChangeLog:

	* trans-array.cc (non_negative_strides_array_p): Inline variable
	orig_decl and merge nested if conditions.  Add condition to not
	recurse if the next argument is the same as the current.

gcc/testsuite/ChangeLog:

	* gfortran.dg/character_array_dummy_1.f90: New test.
This commit is contained in:
Mikael Morin 2022-04-27 11:36:00 +02:00
parent 6c211e70eb
commit 3e0c9fdfd0
2 changed files with 25 additions and 3 deletions

View File

@ -3696,9 +3696,10 @@ non_negative_strides_array_p (tree expr)
/* If the array was originally a dummy with a descriptor, strides can be
negative. */
if (DECL_P (expr)
&& DECL_LANG_SPECIFIC (expr))
if (tree orig_decl = GFC_DECL_SAVED_DESCRIPTOR (expr))
return non_negative_strides_array_p (orig_decl);
&& DECL_LANG_SPECIFIC (expr)
&& GFC_DECL_SAVED_DESCRIPTOR (expr)
&& GFC_DECL_SAVED_DESCRIPTOR (expr) != expr)
return non_negative_strides_array_p (GFC_DECL_SAVED_DESCRIPTOR (expr));
return true;
}

View File

@ -0,0 +1,21 @@
! { dg-do compile }
!
! PR fortran/105381
! Infinite recursion with array references of character dummy arguments.
!
! Contributed by Harald Anlauf <anlauf@gmx.de>
MODULE m
implicit none
integer, parameter :: ncrit = 8
integer, parameter :: nterm = 7
contains
subroutine new_thin_rule (rule1)
character(*),intent(in) ,optional :: rule1(ncrit)
character(len=8) :: rules (ncrit,nterm)
rules = ''
if (present (rule1)) rules(:,1) = rule1 ! <-- compile time hog
end subroutine new_thin_rule
end module m