@@ -962,6 +962,8 @@ tree
gfc_get_array_span (tree desc, gfc_expr *expr)
{
tree tmp;
+ gfc_symbol *sym = expr->expr_type == EXPR_VARIABLE
+ ? expr->symtree->n.sym : NULL;
if (is_pointer_array (desc)
|| (get_CFI_desc (NULL, expr, &desc, NULL)
@@ -983,25 +985,43 @@ gfc_get_array_span (tree desc, gfc_expr *expr)
desc = build_fold_indirect_ref_loc (input_location, desc);
tmp = gfc_conv_descriptor_span_get (desc);
}
+ else if (UNLIMITED_POLY (expr)
+ || (sym && UNLIMITED_POLY (sym)))
+ {
+ /* Treat unlimited polymorphic expressions separately because
+ the element size need not be the same as the span. Obtain
+ the class container, which is simplified here by their being
+ no component references. */
+ if (sym && sym->attr.dummy)
+ {
+ tmp = gfc_get_symbol_decl (sym);
+ tmp = GFC_DECL_SAVED_DESCRIPTOR (tmp);
+ if (INDIRECT_REF_P (tmp))
+ tmp = TREE_OPERAND (tmp, 0);
+ }
+ else
+ {
+ gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
+ tmp = TREE_OPERAND (desc, 0);
+ }
+ tmp = gfc_class_data_get (tmp);
+ tmp = gfc_conv_descriptor_span_get (tmp);
+ }
else if (TREE_CODE (desc) == COMPONENT_REF
&& GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
&& GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (desc, 0))))
{
- /* The descriptor is a class _data field and so use the vtable
- size for the receiving span field. */
- tmp = gfc_get_vptr_from_expr (desc);
+ /* The descriptor is a class _data field. Use the vtable size
+ since it is guaranteed to have been set and is always OK for
+ class array descriptors that are not unlimited. */
+ tmp = gfc_class_vptr_get (TREE_OPERAND (desc, 0));
tmp = gfc_vptr_size_get (tmp);
}
- else if (expr && expr->expr_type == EXPR_VARIABLE
- && expr->symtree->n.sym->ts.type == BT_CLASS
- && expr->ref->type == REF_COMPONENT
- && expr->ref->next->type == REF_ARRAY
- && expr->ref->next->next == NULL
- && CLASS_DATA (expr->symtree->n.sym)->attr.dimension)
+ else if (sym && sym->ts.type == BT_CLASS && sym->attr.dummy)
{
- /* Dummys come in sometimes with the descriptor detached from
- the class field or declaration. */
- tmp = gfc_class_vptr_get (expr->symtree->n.sym->backend_decl);
+ /* Class dummys usually requires extraction from the saved
+ descriptor, which gfc_class_vptr_get does for us. */
+ tmp = gfc_class_vptr_get (sym->backend_decl);
tmp = gfc_vptr_size_get (tmp);
}
else
@@ -1,7 +1,7 @@
! { dg-do run }
!
! Tests fix for PR100120/100816/100818/100819/100821
-!
+!
program main_p
@@ -27,10 +27,10 @@ program main_p
character(len=m, kind=k), pointer :: pm(:)
character(len=e, kind=k), pointer :: pe(:)
character(len=:, kind=k), pointer :: pd(:)
-
+
class(*), pointer :: su
class(*), pointer :: pu(:)
-
+
integer :: i, j
nullify(s1, sm, se, sd, su)
@@ -41,7 +41,7 @@ program main_p
cm(i)(j:j) = char(i*m+j+c-m, kind=k)
end do
end do
-
+
s1 => c1(n)
if(.not.associated(s1)) stop 1
if(.not.associated(s1, c1(n))) stop 2
new file mode 100644
@@ -0,0 +1,77 @@
+! { dg-do run }
+!
+! Test the fix for PR109435 in which array references in the SELECT TYPE
+! block below failed because the descriptor span was not set correctly.
+!
+! Contributed by Lauren Chilutti <lchilutti@gmail.com>
+!
+program test
+ implicit none
+ type :: t
+ character(len=12, kind=4) :: str_array(4)
+ integer :: i
+ end type
+ character(len=12, kind=1), target :: str_array(4)
+ character(len=12, kind=4), target :: str_array4(4)
+ type(t) :: str_t (4)
+ integer :: i
+
+ str_array(:) = ""
+ str_array(1) = "12345678"
+ str_array(2) = "@ABCDEFG"
+! Original failing test
+ call foo (str_array)
+
+ str_array4(:) = ""
+ str_array4(1) = "12345678"
+ str_array4(2) = "@ABCDEFG"
+ str_t = [(t(str_array4, i), i = 1, 4)]
+! Test character(kind=4)
+ call foo (str_t(2)%str_array)
+! Test component references
+ call foo (str_t%str_array(1), .true.)
+! Test component references and that array offset is correct.
+ call foo (str_t(2:3)%i)
+
+contains
+ subroutine foo (var, flag)
+ class(*), intent(in) :: var(:)
+ integer(kind=4) :: i
+ logical, optional :: flag
+ select type (var)
+ type is (character(len=*, kind=1))
+ if (len (var) /= 12) stop 1
+! Scalarised array references worked.
+ if (any (var /= str_array)) stop 2
+ do i = 1, size(var)
+! Elemental array references did not work.
+ if (trim (var(i)) /= trim (str_array(i))) stop 3
+ enddo
+
+ type is (character(len=*, kind=4))
+ if (len (var) /= 12) stop 4
+! Scalarised array references worked.
+ if (any (var /= var(1))) then
+ if (any (var /= str_array4)) stop 5
+ else
+ if (any (var /= str_array4(1))) stop 6
+ end if
+ do i = 1, size(var)
+! Elemental array references did not work.
+ if (var(i) /= var(1)) then
+ if (present (flag)) stop 7
+ if (trim (var(i)) /= trim (str_array4(i))) stop 8
+ else
+ if (trim (var(i)) /= trim (str_array4(1))) stop 9
+ end if
+ enddo
+
+ type is (integer(kind=4))
+ if (any(var /= [2,3])) stop 10
+ do i = 1, size (var)
+ if (var(i) /= i+1) stop 11
+ end do
+ end select
+ end
+end
+