[Patch,Fortran] Add polymorphic type support (OOP, RTTI) - merge from Fortran-dev branch

Janus Weil janus@gcc.gnu.org
Thu Oct 1 11:36:00 GMT 2009


Hi Tobias,

>>> attached patch adds more OOP; it is just the difference between the 4.5
>>> trunk and the Fortran-dev branch (with one additional line).
>
> I have now committed the unmodified patch to the trunk as Rev. 152345.

thanks a lot for taking care of the merge. I will have a look at your
comments later (I will be back home tomorrow).

Also: Now that all the OOP stuff has landed on trunk, I would
encourage all interested users (Salvatore, Damian, anyone else?) to
test the current implementation, so that we can quickly fix the
remaining bugs.

Cheers,
Janus



>  * * *
>
> Some comments - (a)-(d) go mostly to Janus, the comment afterwards
> mostly to Paul.
>
> a) SAME_TYPE_AS and EXTENDS_TYPE_OF: I think one could add a
> compile-time simplifier.
>
> b) As shown my posted test program, the following often does not work
> (nested select_type blocks, ...). I think one could have a static global
> linked list, which gets pushed the current variable when entering the
> block and popped when leaving. In the block one then walks through the
> list of variables. And instead of checking the current state, one simply
> checks whether the linked list is NULL.
>
> +  /* Special case: If we're in a SELECT TYPE block,
> +     replace the selector variable by a temporary.  */
> +  if (gfc_current_state () == COMP_SELECT_TYPE
> +      && st && st->n.sym == type_selector)
> +    st = select_type_tmp;
> +
>
> c) Allocation of abstract types requires a type spec or a SOURCE
> type, abstract :: t
> end type t
> class(t), allocatable :: a
> allocate(a) ! missing type-spec/source=
> allocate(a, source=b) ! Wrong: b is abstract
>                      ! though only checkable at runtime
> end
>
>  * * *
>
> Similarly to Daniel, I do not think that the current vtable
> implementation is sufficient. For instance the following program fails
> to compile although it is valid - here all items are "TYPE IS" and all
> types are known via use association, but still it fails.
>
> ========= File: bb.f90 =========
> module m
> type t
> end type t
> end module m
> ========= File: cc.f90 =========
> module m2
>  use m
>  type, extends(t) :: t2
>  end type t2
> end module m2
> ========= File: dd.f90 =========
> use m
> use m2
> type,extends(t) :: t3
> end type t3
>
> integer :: i
> class(t), allocatable :: a
> allocate(t3 :: a)
> select type(a)
>  type is(t)
>    i = 1
>  type is(t2)
>    i = 2
>  type is(t3)
>    i = 3
> end select
> print *, i
> end
> ========================
>
> The error message is:
>
> $ gfortran bb.f90 cc.f90 dd.f90
> dd.f90:10.10:
>
>  type is(t)
>          1
> dd.f90:12.10:
>
>  type is(t2)
>          2
> Error: CASE label at (1) overlaps with CASE label at (2)
>
>  * * *
>
> Tobias
>
> PS: Daniel's comments should also be answered:
>> here are some comments while reading through the patch:
>>
>> +      if (argss == gfc_ss_terminator)
>> +            {
>> +          gfc_conv_expr_reference (&parmse, e);
>> +          tmp = fold_convert (TREE_TYPE (data),
>> +                  parmse.expr);
>> +          gfc_add_modify (&parmse.pre, data, tmp);
>> +        }
>>
>> It seems the white-space of the opening curly brace is messed up.
>>
>>
>> +  if (derived->attr.extension)
>> +    return gfc_get_ultimate_derived_super_type (derived);
>> +  else
>> +    return derived;
>>
>> I like the tail-recursive style here instead of a loop :)
>>
>> +  (*as) = NULL;  /* XXX */
>>
>> What's about this one?
>>
>> +/* Counter for assigning a unique vindex number to each derived
>> type.  */
>> +static int vindex_counter = 0;
>> +
>> +
>>  /* Match the beginning of a derived type declaration.  If a type name
>>     was the result of a function, then it is possible to have a symbol
>>     already to be known as a derived type yet have no components.  */
>> @@ -6823,6 +6896,10 @@ gfc_match_derived_decl (void)
>>        st->n.sym = sym;
>>      }
>>
>> +  if (!sym->vindex)
>> +    /* Set the vindex for this type and increment the counter.  */
>> +    sym->vindex = ++vindex_counter;
>> +
>>
>> I'm not really sure about the way vindices are calculated and this
>> looks quite fine...  But is this safe even with types in multiple
>> modules combined and stuff like that?  Or different compilation units?
>>
>> +  if (!pointer && !proc_pointer
>> +    && !(lvalue->ts.type == BT_CLASS
>> +        && lvalue->ts.u.derived->components->attr.pointer))
>>
>> I'm not sure how you handle this, but maybe you could set the
>> attributes on the container to the same as the declared type component
>> and get rid of checks like that?  Would that work?
>>
>> +  if (sym->ts.type == BT_CLASS)
>> +    {
>> +      allocatable = sym->ts.u.derived->components->attr.allocatable;
>> +      pointer = sym->ts.u.derived->components->attr.pointer;
>> +    }
>> +  else
>> +    {
>> +      allocatable = sym->attr.allocatable;
>> +      pointer = sym->attr.pointer;
>> +    }
>>
>> Ditto (and some others like that).
>>
>> +    case EXEC_SELECT_TYPE:
>> +      /* Do nothing. SELECT TYPE statements should be transformed into
>> +      an ordinary SELECT CASE at resolution stage.
>> +      TODO: Add an error message here once this is done.  */
>> +      res = NULL_TREE;
>> +      break;
>>
>> What's with this, shouldn't there be an unreachable or assertion, now
>> that I assume the transformation is really already done?
>>
>> +      /* Kill the dead block, but not the blocks below it.  */
>>
>> ...which raises the important question, if something dead can be
>> killed?  Just ignore me here, though :)
>



More information about the Fortran mailing list