aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/class.c
diff options
context:
space:
mode:
authorPaul Thomas <pault@gcc.gnu.org>2015-01-18 22:01:29 +0000
committerPaul Thomas <pault@gcc.gnu.org>2015-01-18 22:01:29 +0000
commit5b384b3d55927e813a97f4cd7aaef89df59ab1d8 (patch)
tree8897cf52c9332ef304732836b3ee4b66ef2cbb2c /gcc/fortran/class.c
parent69fe4502488fea1573f2d5166235540e3d9a466e (diff)
downloadgcc-5b384b3d55927e813a97f4cd7aaef89df59ab1d8.zip
gcc-5b384b3d55927e813a97f4cd7aaef89df59ab1d8.tar.gz
gcc-5b384b3d55927e813a97f4cd7aaef89df59ab1d8.tar.bz2
[multiple changes]
2015-01-18 Andre Vehreschild <vehre@gmx.de> Janus Weil <janus@gcc.gnu.org> PR fortran/60255 * class.c (gfc_get_len_component): New. (gfc_build_class_symbol): Add _len component to unlimited polymorphic entities. (find_intrinsic_vtab): Removed emitting of error message. * gfortran.h: Added prototype for gfc_get_len_component. * simplify.c (gfc_simplify_len): Use _len component where available. * trans-expr.c (gfc_class_len_get): New. (gfc_conv_intrinsic_to_class): Add handling for deferred character arrays. (gfc_conv_structure): Treat _len component correctly. (gfc_conv_expr): Prevent bind_c handling when not required. (gfc_trans_pointer_assignment): Propagate _len component. * trans-stmt.c (class_has_len_component): New. (trans_associate_var): _len component treatment for associate context. (gfc_trans_allocate): Same as for trans_associate_var() * trans.h: Added prototype for gfc_class_len_get. 2015-01-18 Andre Vehreschild <vehre@gmx.de> PR fortran/60255 * gfortran.dg/unlimited_polymorphic_2.f03: Removed error. * gfortran.dg/unlimited_polymorphic_20.f03: New test. 2015-01-18 Paul Thomas <pault@gcc.gnu.org> PR fortran/64578 * gfortran.dg/unlimited_polymorphic_21.f90: New test From-SVN: r219827
Diffstat (limited to 'gcc/fortran/class.c')
-rw-r--r--gcc/fortran/class.c76
1 files changed, 60 insertions, 16 deletions
diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
index dcbbdc7..a9b65e6 100644
--- a/gcc/fortran/class.c
+++ b/gcc/fortran/class.c
@@ -34,6 +34,12 @@ along with GCC; see the file COPYING3. If not see
(pointer/allocatable/dimension/...).
* _vptr: A pointer to the vtable entry (see below) of the dynamic type.
+ Only for unlimited polymorphic classes:
+ * _len: An integer(4) to store the string length when the unlimited
+ polymorphic pointer is used to point to a char array. The '_len'
+ component will be zero when no character array is stored in
+ '_data'.
+
For each derived type we set up a "vtable" entry, i.e. a structure with the
following fields:
* _hash: A hash value serving as a unique identifier for this type.
@@ -544,10 +550,48 @@ gfc_intrinsic_hash_value (gfc_typespec *ts)
}
+/* Get the _len component from a class/derived object storing a string.
+ For unlimited polymorphic entities a ref to the _data component is available
+ while a ref to the _len component is needed. This routine traverese the
+ ref-chain and strips the last ref to a _data from it replacing it with a
+ ref to the _len component. */
+
+gfc_expr *
+gfc_get_len_component (gfc_expr *e)
+{
+ gfc_expr *ptr;
+ gfc_ref *ref, **last;
+
+ ptr = gfc_copy_expr (e);
+
+ /* We need to remove the last _data component ref from ptr. */
+ last = &(ptr->ref);
+ ref = ptr->ref;
+ while (ref)
+ {
+ if (!ref->next
+ && ref->type == REF_COMPONENT
+ && strcmp ("_data", ref->u.c.component->name)== 0)
+ {
+ gfc_free_ref_list (ref);
+ *last = NULL;
+ break;
+ }
+ last = &(ref->next);
+ ref = ref->next;
+ }
+ /* And replace if with a ref to the _len component. */
+ gfc_add_component_ref (ptr, "_len");
+ return ptr;
+}
+
+
/* Build a polymorphic CLASS entity, using the symbol that comes from
build_sym. A CLASS entity is represented by an encapsulating type,
which contains the declared type as '_data' component, plus a pointer
- component '_vptr' which determines the dynamic type. */
+ component '_vptr' which determines the dynamic type. When this CLASS
+ entity is unlimited polymorphic, then also add a component '_len' to
+ store the length of string when that is stored in it. */
bool
gfc_build_class_symbol (gfc_typespec *ts, symbol_attribute *attr,
@@ -645,19 +689,28 @@ gfc_build_class_symbol (gfc_typespec *ts, symbol_attribute *attr,
if (!gfc_add_component (fclass, "_vptr", &c))
return false;
c->ts.type = BT_DERIVED;
+ c->attr.access = ACCESS_PRIVATE;
+ c->attr.pointer = 1;
if (ts->u.derived->attr.unlimited_polymorphic)
{
vtab = gfc_find_derived_vtab (ts->u.derived);
gcc_assert (vtab);
c->ts.u.derived = vtab->ts.u.derived;
+
+ /* Add component '_len'. Only unlimited polymorphic pointers may
+ have a string assigned to them, i.e., only those need the _len
+ component. */
+ if (!gfc_add_component (fclass, "_len", &c))
+ return false;
+ c->ts.type = BT_INTEGER;
+ c->ts.kind = 4;
+ c->attr.access = ACCESS_PRIVATE;
+ c->attr.artificial = 1;
}
else
/* Build vtab later. */
c->ts.u.derived = NULL;
-
- c->attr.access = ACCESS_PRIVATE;
- c->attr.pointer = 1;
}
if (!ts->u.derived->attr.unlimited_polymorphic)
@@ -2415,18 +2468,9 @@ find_intrinsic_vtab (gfc_typespec *ts)
gfc_symbol *copy = NULL, *src = NULL, *dst = NULL;
int charlen = 0;
- if (ts->type == BT_CHARACTER)
- {
- if (ts->deferred)
- {
- gfc_error ("TODO: Deferred character length variable at %C cannot "
- "yet be associated with unlimited polymorphic entities");
- return NULL;
- }
- else if (ts->u.cl && ts->u.cl->length
- && ts->u.cl->length->expr_type == EXPR_CONSTANT)
- charlen = mpz_get_si (ts->u.cl->length->value.integer);
- }
+ if (ts->type == BT_CHARACTER && !ts->deferred && ts->u.cl && ts->u.cl->length
+ && ts->u.cl->length->expr_type == EXPR_CONSTANT)
+ charlen = mpz_get_si (ts->u.cl->length->value.integer);
/* Find the top-level namespace. */
for (ns = gfc_current_ns; ns; ns = ns->parent)