fortran: Compare non-constant bound expressions. [PR105379]

Starting with r12-8235-gfa5cd7102da676dcb1757b1288421f5f3439ae0e,
class descriptor types are compared to detect duplicate declarations.

This caused ICEs as the comparison of array spec supported only constant
explicit bounds, but dummy class variable descriptor types can have a
_data field with non-constant array spec bounds.

This change adds support for non-constant bounds.  For that,
gfc_dep_compare_expr is used.  It does probably more than strictly
necessary, but using it avoids rewriting a specific comparison function,
making mistakes and forgetting cases.

	PR fortran/103662
	PR fortran/105379

gcc/fortran/ChangeLog:

	* array.cc (compare_bounds): Use bool as return type.
	Support non-constant expressions.
	(gfc_compare_array_spec): Update call to compare_bounds.

gcc/testsuite/ChangeLog:

	* gfortran.dg/class_dummy_8.f90: New test.
	* gfortran.dg/class_dummy_9.f90: New test.
This commit is contained in:
Mikael Morin 2022-04-27 11:36:16 +02:00
parent 3e0c9fdfd0
commit 6a460a2007
3 changed files with 56 additions and 11 deletions

View File

@ -957,23 +957,28 @@ gfc_copy_array_spec (gfc_array_spec *src)
}
/* Returns nonzero if the two expressions are equal. Only handles integer
constants. */
/* Returns nonzero if the two expressions are equal.
We should not need to support more than constant values, as thats what is
allowed in derived type component array spec. However, we may create types
with non-constant array spec for dummy variable class container types, for
which the _data component holds the array spec of the variable declaration.
So we have to support non-constant bounds as well. */
static int
static bool
compare_bounds (gfc_expr *bound1, gfc_expr *bound2)
{
if (bound1 == NULL || bound2 == NULL
|| bound1->expr_type != EXPR_CONSTANT
|| bound2->expr_type != EXPR_CONSTANT
|| bound1->ts.type != BT_INTEGER
|| bound2->ts.type != BT_INTEGER)
gfc_internal_error ("gfc_compare_array_spec(): Array spec clobbered");
if (mpz_cmp (bound1->value.integer, bound2->value.integer) == 0)
return 1;
else
return 0;
/* What qualifies as identical bounds? We could probably just check that the
expressions are exact clones. We avoid rewriting a specific comparison
function and re-use instead the rather involved gfc_dep_compare_expr which
is just a bit more permissive, as it can also detect identical values for
some mismatching expressions (extra parenthesis, swapped operands, unary
plus, etc). It probably only makes a difference in corner cases. */
return gfc_dep_compare_expr (bound1, bound2) == 0;
}
@ -1006,10 +1011,10 @@ gfc_compare_array_spec (gfc_array_spec *as1, gfc_array_spec *as2)
if (as1->type == AS_EXPLICIT)
for (i = 0; i < as1->rank + as1->corank; i++)
{
if (compare_bounds (as1->lower[i], as2->lower[i]) == 0)
if (!compare_bounds (as1->lower[i], as2->lower[i]))
return 0;
if (compare_bounds (as1->upper[i], as2->upper[i]) == 0)
if (!compare_bounds (as1->upper[i], as2->upper[i]))
return 0;
}

View File

@ -0,0 +1,20 @@
! { dg-do compile }
!
! PR fortran/105379
! Type comparison of class containers used to trigger an ICE when one of the
! class containers had a non-constant array spec.
!
! Contributed by Gerhard Steinmetz <gscfq@t-online.de>.
program p
type t
end type
contains
subroutine s1(x)
class(t) :: x(3)
end
subroutine s2(n, x)
integer :: n
class(t) :: x(n)
end
end

View File

@ -0,0 +1,20 @@
! { dg-do compile }
!
! PR fortran/105379
! Type comparison of class containers used to trigger an ICE when one of the
! class containers had a non-constant array spec.
!
! Contributed by Gerhard Steinmetz <gscfq@t-online.de>.
program p
type t
end type
integer :: m = 3
contains
subroutine s1(x)
class(t) :: x(3)
end
subroutine s3(x)
class(t) :: x(m)
end
end