diff --git a/gcc/fortran/array.cc b/gcc/fortran/array.cc index 90ea812d699..bbdb5b392fc 100644 --- a/gcc/fortran/array.cc +++ b/gcc/fortran/array.cc @@ -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 that’s 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; } diff --git a/gcc/testsuite/gfortran.dg/class_dummy_8.f90 b/gcc/testsuite/gfortran.dg/class_dummy_8.f90 new file mode 100644 index 00000000000..0976a725866 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/class_dummy_8.f90 @@ -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 . + +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 diff --git a/gcc/testsuite/gfortran.dg/class_dummy_9.f90 b/gcc/testsuite/gfortran.dg/class_dummy_9.f90 new file mode 100644 index 00000000000..0fd98c05be2 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/class_dummy_9.f90 @@ -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 . + +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