Patch to enable unlimited polymorphism to gfortran

Tobias Burnus burnus@net-b.de
Sun Dec 16 14:31:00 GMT 2012


Thanks for the patch, here is a first but incomplete review. I think the 
patch looks mostly okay.


Running your test cases through crayftn, I found:

   if (SAME_TYPE_AS (obj1, u1) .neqv. .FALSE.) call abort
                           ^
ftn-1698 crayftn: ERROR $MAIN, File = unlimited_polymorphic_1.f03, Line 
= 67, Column = 27
Type INTEGER(kind=4) is not allowed for the "B" argument of intrinsic 
SAME_TYPE_AS.

The message itself is correct. However, Paul mentioned off-list that 
"obj1" and "u1" are both extensible types and, hence, neither is an 
"integer(kind=4)". In any case, if either of them were an integer(4) it 
would be invalid:

 From Fortran 2008's "13.7.142 SAME_TYPE_AS (A, B)"
"Arguments.
"A shall be an object of extensible declared type or unlimited 
polymorphic. If it is a pointer, it shall not have an undefined 
association status.
"B shall be an object of extensible declared type or unlimited 
polymorphic. If it is a pointer, it shall
not have an undefined association status."

Ditto for "13.7.60 EXTENDS TYPE OF (A, MOLD)".

At least for -std=f2003/f2008 we have to reject nonextensible, 
non-unlimited-polymorphic arguments. - Even if a supporting intrinsic 
types were a nice addition.


Paul Richard Thomas wrote:
> +
> +       if (UNLIMITED_POLY (c->expr))
> + 	{
> + 	  gfc_error ("F08: C4106 array constructor value at %L shall not be "
> + 		     " unlimited polymorphic", &c->expr->where);
> + 	  t = FAILURE;

You have a " " at both then end and the beginning of the line. 
Additionally, I wonder how we want to inform the user about those 
constrains. So far, we always had the message only without reference to 
the standard. Having one, is not bad, the question is only where. I 
would favor to have the information at the end, given that gfortran 
currently prints "Fortran 2008:" if a something is only valid in Fortran 
2008 and later. Additionally, I personally don't like "F08" that much 
and prefer "Fortran 2008" (or at least "F2008"). Thus, I'd use something 
like:

+ 	  gfc_error ("Array constructor value at %L shall not be unlimited"
+ 		     " polymorphic [Fortran 2008, C4106]", &c->expr->where);


(Except for the double " ", that's bikeshadding; hence, I leave it to 
you. The "F08: C..." also occures at other places in the patch)



+    sprintf (dt_name, "%s", "$tar");

(Off-topic question for mere curiosity: Why "$tar"?)

> + gfc_find_intrinsic_vtab (gfc_typespec *ts)
>
> +   if (ts->type == BT_CHARACTER && ts->deferred)
> +     {
> +       gfc_error ("TODO: Deferred character length variable at %C cannot "
> + 		 "yet be associated with unlimited polymorphic entities");

The same issue also applies to assumed-length strings. At least the 
following program prints:
            0 ""
            0 ""
I think we have to fill a PR which lists all of the known deficits of 
the current implementation. Besides the string issue, that's also the 
renaming of gfc_find_intrinsic_vtab into gfc_find_derived_vtab.

Here's the test case:

call foo("Hello")
call foo("World!")
contains
subroutine foo(str)
   character(len=*), target :: str
   class(*), pointer :: up
   up => str
   call bar(up)
end subroutine foo
subroutine bar(x)
   class(*) :: x

   select type(x)
     type is (character(len=*))
       print *, len(x), '"'//x//'"'
   end select
end subroutine bar
end



> + #define UNLIMITED_POLY(sym) (sym != NULL && sym->ts.type == BT_CLASS && CLASS_DATA (sym) \
> + 			&& CLASS_DATA (sym)->ts.u.derived \
> + 			&& CLASS_DATA (sym)->ts.u.derived->attr.unlimited_polymorphic)

The lines are way too long: 90 and 86 characters.


> +   sprintf (name, "__tmp_%s_%d", gfc_basic_typename (ts->type),
> + 	   ts->type == BT_CHARACTER ? charlen : ts->kind);

How do you distinguish between character(kind=1) and character(kind=4)? 
The same issue exists for a like-wise code in resolve_select_type.


+  /* Unlimited polymorphic pointers should have their vptr nullified.  */
+  if (UNLIMITED_POLY (sym) && CLASS_DATA (sym)->attr.pointer)
+    gfc_defer_symbol_init (sym);


Why? If the pointer has never been pointer-associated, one shouldn't 
access it. Thus, the code is not need. If it is needed, I fear that code 
will also break when one later deallocates/nullifies the pointer. I 
think _vptr should only be set when also nonpolymorphic CLASS get their 
_vptr set. For pointers, that's presumably only ALLOCATE and 
pointer-association.


Tobias



More information about the Gcc-patches mailing list