type = TREE_TYPE (TREE_OPERAND (cdesc, 0));
if (TYPE_CANONICAL (type)
&& GFC_CLASS_TYPE_P (TYPE_CANONICAL (type)))
- vptr = gfc_class_vptr_get (TREE_OPERAND (cdesc, 0));
+ {
+ vptr = gfc_class_vptr_get (TREE_OPERAND (cdesc, 0));
+ /* Pass the class container as decl so that gfc_build_array_ref can
+ correct the element size for an unlimited polymorphic character
+ payload (the _len field), which the vptr size alone omits. Only do
+ this for a genuine array element reference; a scalar coarray has
+ nothing to span-correct and gfc_build_array_ref asserts decl is null
+ for it. */
+ if (decl == NULL_TREE
+ && GFC_TYPE_ARRAY_RANK (TREE_TYPE (cdesc)) > 0)
+ decl = TREE_OPERAND (cdesc, 0);
+ }
}
tmp = gfc_conv_array_data (desc);
case BT_CLASS:
basetype = gfc_get_derived_type (spec->u.derived, codim);
- if (spec->type == BT_CLASS)
- GFC_CLASS_TYPE_P (basetype) = 1;
-
/* If we're dealing with either C_PTR or C_FUNPTR, we modified the
type and kind to fit a (void *) and the basetype returned was a
ptr_type_node. We need to pass up this new information to the
TYPE_NAME (typenode) = get_identifier (derived->name);
TYPE_PACKED (typenode) = flag_pack_derived;
derived->backend_decl = typenode;
+ if (derived->attr.is_class)
+ GFC_CLASS_TYPE_P (typenode) = 1;
}
if (derived->components
field_type = build_pointer_type_for_mode (TREE_TYPE (field_type),
ptr_mode, true);
- /* Ensure that the CLASS language specific flag is set. */
- if (c->ts.type == BT_CLASS)
- {
- if (POINTER_TYPE_P (field_type))
- GFC_CLASS_TYPE_P (TREE_TYPE (field_type)) = 1;
- else
- GFC_CLASS_TYPE_P (field_type) = 1;
- }
-
field = gfc_add_field_to_struct (typenode,
get_identifier (c->name),
field_type, &chain);
break;
}
+ if (derived->attr.is_class)
+ GFC_CLASS_TYPE_P (derived->backend_decl) = 1;
+
return derived->backend_decl;
}
--- /dev/null
+! { dg-do run }
+!
+! PR fortran/125761
+!
+! Passing an array section of an unlimited-polymorphic array with a CHARACTER
+! payload addressed the section data with the wrong element size: the section
+! base data pointer was offset using the vptr size (the kind size, 1) rather
+! than the _len-corrected element size, so every element but the first was
+! wrong.
+
+program p
+ character(4), target :: arr(5) = ["aaaa", "bbbb", "cccc", "dddd", "eeee"]
+ character(2), target :: arr2(4) = ["xx", "yy", "zz", "ww"]
+ class(*), pointer :: ptr(:)
+
+ ptr => arr
+ call check (ptr(2:4), ["bbbb", "cccc", "dddd"]) ! contiguous
+ call check (ptr(1:5:2), ["aaaa", "cccc", "eeee"]) ! strided
+
+ ptr => arr2
+ call check (ptr(2:3), ["yy", "zz"])
+
+contains
+
+ subroutine check (x, expect)
+ class(*) :: x(:)
+ character(*), intent(in) :: expect(:)
+ integer :: i
+ select type (x)
+ type is (character(*))
+ if (len (x) /= len (expect)) stop 1
+ if (size (x) /= size (expect)) stop 2
+ do i = 1, size (x)
+ if (x(i) /= expect(i)) stop 3
+ end do
+ class default
+ stop 4
+ end select
+ end subroutine
+
+end program p