diff options
author | Paul Thomas <pault@gcc.gnu.org> | 2015-01-18 22:01:29 +0000 |
---|---|---|
committer | Paul Thomas <pault@gcc.gnu.org> | 2015-01-18 22:01:29 +0000 |
commit | 5b384b3d55927e813a97f4cd7aaef89df59ab1d8 (patch) | |
tree | 8897cf52c9332ef304732836b3ee4b66ef2cbb2c /gcc/fortran/class.c | |
parent | 69fe4502488fea1573f2d5166235540e3d9a466e (diff) | |
download | gcc-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.c | 76 |
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) |