[Patch, Fortran] (Coarray) Fix constraint checks for LOCK_TYPE
Tobias Burnus
burnus@net-b.de
Wed Aug 3 15:55:00 GMT 2011
Mikael,
first, thanks for carefully reading the patch!
On 08/03/2011 01:43 PM, Mikael Morin wrote:
> > PS: It somehow took me quite some time to understand "subcomponent" even
> > though the standard is rather clear about it.
> Is it? It seems I haven't understood the constraint as you did.
It's like the famous saying: "Unix is user friendly, it is just picky
about its friends."
Regarding this part of the standard, I only feel acquainted but not
being a real friend ... I think it is clearly stated in the standard,
but I continue to struggle to apply it correctly.
> So basically, one looks at the components of a structure, and the components
> of all the non-allocatable non-pointer derived type components (and so on
> recursively...).
That's also my reading.
> Among those components, if one has type LOCK_TYPE and is not a coarray, then the enclosing variable shall be a coarray (which seems to mean that all
> variables of this type have to be a coarray).
Yes, I think that's what the constraint requires at the end: In
LOCK(expr) the "expr" needs to be a coarray - or coindexed (such that it
were a coarray without the coindex).
> Though variables in the general case can be components, I don't think it is
> the case here as only named variables are involved here.
> Does that sound right?
The first part of the sentence sounds wrong: A component itself is not a
variable. I think you mean a "structure-component" - and for "var%comp"
both "var%comp" and "var" are variables and I belief both "var%comp" and
"var" are named.
"R602 variable is designator or expr"
"R601 designator is object-name or ... or structure-component"
"R613 structure-component is data-ref"
"R611 data-ref is part-ref [ % part-ref ]"
"R612 part-ref is part-name [ ( section-subscript-list ) ] [
image-selector ]"
> > /* Looking for lock_type components. */
> > - if (c->attr.lock_comp
> > - || (sym->ts.type == BT_DERIVED
> > + if ((c->ts.type == BT_DERIVED
> > && c->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
> > - && c->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE))
> > - sym->attr.lock_comp = 1;
> > + && c->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE)
> > + || (c->ts.type == BT_CLASS && c->attr.class_ok
> > + && CLASS_DATA (c)->ts.u.derived->from_intmod
> > + == INTMOD_ISO_FORTRAN_ENV
> > + && CLASS_DATA (c)->ts.u.derived->intmod_sym_id
> > + == ISOFORTRAN_LOCK_TYPE))
> > + {
> > + if (pointer)
> > + gfc_error ("Pointer component %s at %L of LOCK_TYPE must be a "
> > + "coarray", c->name, &c->loc);
> ... this is wrong as the constraint should be on the variable, not on the
> components of its type.
I think you are right: The derived-type declaration itself is valid
according to the standard - one just may not use it for variable
declaration.
The question is: Should we bother? Is there some genuine interest in
supporting valid but unusable type declarations? The problem is that
diagnosing the problem can get rather difficult. For instance:
type t
type(lock_type) :: C
end type
type t2
type(t), allocatable :: B
end type t2
type t3
type(t2) :: D
end type t3
is valid - however, it is invalid to use:
type(t) :: x[*], y
However, how to write then the error message? "Error: Invalid
declaration at (1) as constraint C642 is violated" is probably not very
helpful, but should one really re-resolve the derived type? There are
also many possible solutions:
"B" should be a coarray, "C" could be also allocatable and a coarray, or
"B" could be not allocatable and "D" or "y" could be a coarray.
Thus, writing a nice and helpful message gets pretty complicated. And,
as written, I do not see a compelling reason for not diagnosing it at
type-declaration time - even if the type is formally correct.
Regarding the check itself - if one assumes that one wants to have an
error, I believe that part is correct. If there is a pointer, it cannot
be valid. Example 1:
type t
type(lock_type), pointer :: lock1
end type t
I cannot write "lock1[:]" as in components, only allocatables are allowed:
"C442 (R436) If a coarray-spec appears, it shall be a
deferred-coshape-spec-list and the component shall have the ALLOCATABLE
attribute."
Turning the variable into a coarray as in
type(t) :: x[*]
does not help: the x%lock1 is not a coarray. "A subobject of a coarray
is a coarray if it does not have any cosubscripts, vector subscripts,
allocatable component selection, or pointer component selection." (Sect.
2.4.7)
On the other hand, if "type t" contains a noncoarray lock_type, one
cannot do use "type(t), pointer :: ptrcomp" as "...%ptrcomp%lock"
wouldn't be a coarray (cf. above) - and if "lock" in "...%ptrcomp%lock"
were a coarray, it would be invalid as: "C444 A data component whose
type has a coarray ultimate component shall be a nonpointer
nonallocatable scalar and shall not be a coarray."
Having said that, I just realized that the following program is not
rejected but it should:
use iso_fortran_env
type t
type(lock_type) :: lock
end type t
type t2
type(t), pointer :: x
end type t2
end
The modified section of the patch would then be:
/* Looking for lock_type components. */
if ((c->ts.type == BT_DERIVED
&& c->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
&& c->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE)
|| (c->ts.type == BT_CLASS && c->attr.class_ok
&& CLASS_DATA (c)->ts.u.derived->from_intmod
== INTMOD_ISO_FORTRAN_ENV
&& CLASS_DATA (c)->ts.u.derived->intmod_sym_id
== ISOFORTRAN_LOCK_TYPE)
|| (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.lock_comp
&& !allocatable && !pointer))
{
lock_type = 1;
lock_comp = c;
sym->attr.lock_comp = 1;
}
/* F2008, C1302. */
if (pointer && !coarray && (lock_type
|| (c->ts.type == BT_DERIVED
&& c->ts.u.derived->attr.lock_comp)))
gfc_error ("Component %s at %L of LOCK_TYPE or with LOCK_TYPE "
"component is a pointer but not a coarray",
c->name, &c->loc);
[...]
> > + if (sym->attr.lock_comp && coarray && !lock_type)
> > + gfc_error ("Component %s at %L of LOCK_TYPE or with LOCK_TYPE has to "
>> > + "be a coarray as %s at %L has a codimension",
>> > + lock_comp->name, &lock_comp->loc, c->name, &c->loc);
> Same here (the three of them) the constraint is not on components.
Here, something similar applies:
type t
integer, allocatable :: caf_comp[:]
type(lock_type) :: lock
end type t
type(t) :: x[*]
It is invalid to make "x" a coarray as "t" already has coarray
components - but if I don't make "x" a coarray, x%lock is not a coarray,
which is invalid.
Thus, I believe there is no way that this error is printed for a type
declaration which can be used to create a valid named variable.
>> > + || (!gfc_is_coarray (code->expr1) && !gfc_is_coindexed (code-
>> >expr1)))
> This part is quite OK.
> I have the feeling that !gfc_is_coindexed is superfluous once one has
> !gfc_is_coarray.
> I'm also not sure that the removal of `coarray' in the error message is
> needed as C1302 forces LOCK_TYPE entities to be coarrays or subobjects of
> coarrays.
The LOCK_TYPE named object needs to be a coarray - the entity you pass
to LOCK does not have to be a coarray. Example:
type(lock_type), type :: lock[*]
LOCK(lock) ! (1)
LOCK(lock[1]) ! (2)
In (1), the argument is a scalar coarray of lock_type. But in (2) one
does not have a coarray but just a coindexed scalar of lock_type.
As "lock[1]" is not a coarray, I believe removing "coarray" from the
error message makes sense as does checking for both gfc_is_coarray and
gfc_is_coindexed.
> Looks like it's not sufficient.
> One can have a non-coarray LOCK_TYPE component and an other component that is
> a coarray.
That's the reason for all the checks in parse.c. I make use of the fact
that one cannot have more than one coarray - if a component is a
coarray, the variable cannot be a coarray and vice versa. I think I have
covered all cases there, but I might be wrong (as I already have been
for the pointer, cf. above).
> > @@ -0,0 +1,7 @@
> > +! { dg-do compile }
> > +! { dg-options "-fcoarray=single" }
> > +!
> > +!
> > +! LOCK/LOCK_TYPE checks
> > +!
> > +
> This one was passing already, wasn't it? ;-)
Hopefully!
Tobias
More information about the Fortran
mailing list