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

Reply via email to